calling this done.. hopefully

master
joey 2007-02-21 09:07:40 +00:00
parent 68784b593f
commit 160568ca2a
1 changed files with 10 additions and 97 deletions

View File

@ -7,6 +7,8 @@ This can happen because CGI.pm writes the change, then drops the main wiki
lock before calling rcs_commit. It can't keep the lock because the commit
hook needs to be able to lock.
-------
We batted this around for an hour or two on irc. The best solution seems to
be adding a subsidiary second lock, which is only used to lock the working
copy and is a blocking read/write lock.
@ -34,103 +36,7 @@ original race. It should be possible though to use a separate exclusive lock,
wrapped around these flock calls, to force them to be "atomic" and avoid that
race.
Sample patch, with stub functions for the new lock:
[[toggle text="expand patch"]]
[[toggleable text="""
<pre>
Index: IkiWiki/CGI.pm
===================================================================
--- IkiWiki/CGI.pm (revision 2774)
+++ IkiWiki/CGI.pm (working copy)
@@ -494,9 +494,14 @@
$content=~s/\r\n/\n/g;
$content=~s/\r/\n/g;
+ lockwc_exclusive();
+
$config{cgi}=0; # avoid cgi error message
eval { writefile($file, $config{srcdir}, $content) };
$config{cgi}=1;
+
+ lockwc_shared();
+
if ($@) {
$form->field(name => "rcsinfo", value => rcs_prepedit($file),
force => 1);
Index: IkiWiki/Plugin/poll.pm
===================================================================
--- IkiWiki/Plugin/poll.pm (revision 2770)
+++ IkiWiki/Plugin/poll.pm (working copy)
@@ -120,7 +120,9 @@
$content =~ s{(\\?)\[\[poll\s+([^]]+)\s*\]\]}{$edit->($1, $2)}seg;
# Store their vote, update the page, and redirect to it.
+ IkiWiki::lockwc_exclusive();
writefile($pagesources{$page}, $config{srcdir}, $content);
+ IkiWiki::lockwc_shared();
$session->param($choice_param, $choice);
IkiWiki::cgi_savesession($session);
$oldchoice=$session->param($choice_param);
@@ -130,6 +132,10 @@
IkiWiki::rcs_commit($pagesources{$page}, "poll vote ($choice)",
IkiWiki::rcs_prepedit($pagesources{$page}),
$session->param("name"), $ENV{REMOTE_ADDR});
+ # Make sure that the repo is up-to-date;
+ # locking prevents the post-commit hook
+ # from updating it.
+ rcs_update();
}
else {
require IkiWiki::Render;
Index: ikiwiki.in
===================================================================
--- ikiwiki.in (revision 2770)
+++ ikiwiki.in (working copy)
@@ -121,6 +121,7 @@
lockwiki();
loadindex();
require IkiWiki::Render;
+ lockwc_shared();
rcs_update();
refresh();
rcs_notify() if $config{notify};
Index: IkiWiki.pm
===================================================================
--- IkiWiki.pm (revision 2770)
+++ IkiWiki.pm (working copy)
@@ -617,6 +617,29 @@
close WIKILOCK;
} #}}}
+sub lockwc_exclusive () { #{{{
+ # Take an exclusive lock on the working copy.
+ # The lock will be dropped on program exit.
+ # Note: This lock should only be taken _after_ the main wiki
+ # lock.
+
+ # TODO
+} #}}}
+
+sub lockwc_shared () { #{{{
+ # Take a shared lock on the working copy. If an exclusive lock
+ # already exists, downgrade it to a shared lock.
+ # The lock will be dropped on program exit.
+ # Note: This lock should only be taken _after_ the main wiki
+ # lock.
+
+ # TODO
+} #}}}
+
+sub unlockwc () { #{{{
+ close WIKIWCLOCK;
+} #}}}
+
sub loadindex () { #{{{
open (IN, "$config{wikistatedir}/index") || return;
while (<IN>) {
</pre>
"""]]
------
My alternative idea, which seems simpler than all this tricky locking
stuff, is to introduce a new lock file (really a flag file implemented
@ -190,3 +96,10 @@ The commit hook takes them in the order (wclock, wikilock). This is a
classic potential deadlock scenario. _However_, the commit hook should
close the wclock as soon as it successfully opens it, before taking the
wikilock, so I think that's ok.
-----
I've committed an implementation of my idea just above, and it seems to
work, although testing for races etc is tricky. Calling this [[bugs/done]]
unless someone finds a new bug or finds a problem in my thinking above.
--[[Joey]]