* Since the CGI had to drop the wiki lock to avoid deadlocking the
commit hook, it was possible for one CGI to race another one and "win" the commit of both their files. This race has been fixed by adding a new commitlock, which when locked by the CGI, disables the commit hook (except for commit mails). The CGI then takes care of the updates the commit hook would have done.master
parent
24b8343506
commit
c60477228c
26
IkiWiki.pm
26
IkiWiki.pm
|
@ -38,6 +38,7 @@ sub defaultconfig () { #{{{
|
||||||
wikiname => "wiki",
|
wikiname => "wiki",
|
||||||
default_pageext => "mdwn",
|
default_pageext => "mdwn",
|
||||||
cgi => 0,
|
cgi => 0,
|
||||||
|
post_commit => 0,
|
||||||
rcs => '',
|
rcs => '',
|
||||||
notify => 0,
|
notify => 0,
|
||||||
url => '',
|
url => '',
|
||||||
|
@ -601,7 +602,7 @@ sub lockwiki () { #{{{
|
||||||
}
|
}
|
||||||
open(WIKILOCK, ">$config{wikistatedir}/lockfile") ||
|
open(WIKILOCK, ">$config{wikistatedir}/lockfile") ||
|
||||||
error ("cannot write to $config{wikistatedir}/lockfile: $!");
|
error ("cannot write to $config{wikistatedir}/lockfile: $!");
|
||||||
if (! flock(WIKILOCK, 2 | 4)) {
|
if (! flock(WIKILOCK, 2 | 4)) { # LOCK_EX | LOCK_NB
|
||||||
debug("wiki seems to be locked, waiting for lock");
|
debug("wiki seems to be locked, waiting for lock");
|
||||||
my $wait=600; # arbitrary, but don't hang forever to
|
my $wait=600; # arbitrary, but don't hang forever to
|
||||||
# prevent process pileup
|
# prevent process pileup
|
||||||
|
@ -617,6 +618,29 @@ sub unlockwiki () { #{{{
|
||||||
close WIKILOCK;
|
close WIKILOCK;
|
||||||
} #}}}
|
} #}}}
|
||||||
|
|
||||||
|
sub commit_hook_enabled () { #{{{
|
||||||
|
open(COMMITLOCK, "+>$config{wikistatedir}/commitlock") ||
|
||||||
|
error ("cannot write to $config{wikistatedir}/commitlock: $!");
|
||||||
|
if (! flock(WIKILOCK, 1 | 4)) { # LOCK_SH | LOCK_NB to test
|
||||||
|
close WIKILOCK;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
close WIKILOCK;
|
||||||
|
return 1;
|
||||||
|
} #}}}
|
||||||
|
|
||||||
|
sub disable_commit_hook () { #{{{
|
||||||
|
open(COMMITLOCK, ">$config{wikistatedir}/commitlock") ||
|
||||||
|
error ("cannot write to $config{wikistatedir}/commitlock: $!");
|
||||||
|
if (! flock(COMMITLOCK, 2)) { # LOCK_EX
|
||||||
|
error("failed to get commit lock");
|
||||||
|
}
|
||||||
|
} #}}}
|
||||||
|
|
||||||
|
sub enable_commit_hook () { #{{{
|
||||||
|
close COMMITLOCK;
|
||||||
|
} #}}}
|
||||||
|
|
||||||
sub loadindex () { #{{{
|
sub loadindex () { #{{{
|
||||||
open (IN, "$config{wikistatedir}/index") || return;
|
open (IN, "$config{wikistatedir}/index") || return;
|
||||||
while (<IN>) {
|
while (<IN>) {
|
||||||
|
|
|
@ -513,6 +513,7 @@ sub cgi_editpage ($$) { #{{{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $conflict;
|
||||||
if ($config{rcs}) {
|
if ($config{rcs}) {
|
||||||
my $message="";
|
my $message="";
|
||||||
if (defined $form->field('comments') &&
|
if (defined $form->field('comments') &&
|
||||||
|
@ -523,13 +524,24 @@ sub cgi_editpage ($$) { #{{{
|
||||||
if ($newfile) {
|
if ($newfile) {
|
||||||
rcs_add($file);
|
rcs_add($file);
|
||||||
}
|
}
|
||||||
# prevent deadlock with post-commit hook
|
|
||||||
unlockwiki();
|
# Prevent deadlock with post-commit hook by
|
||||||
# presumably the commit will trigger an update
|
# signaling to it that it should not try to
|
||||||
# of the wiki
|
# do anything (except send commit mails).
|
||||||
my $conflict=rcs_commit($file, $message,
|
disable_commit_hook();
|
||||||
|
$conflict=rcs_commit($file, $message,
|
||||||
$form->field("rcsinfo"),
|
$form->field("rcsinfo"),
|
||||||
$session->param("name"), $ENV{REMOTE_ADDR});
|
$session->param("name"), $ENV{REMOTE_ADDR});
|
||||||
|
enable_commit_hook();
|
||||||
|
rcs_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
# Refresh even if there was a conflict, since other changes
|
||||||
|
# may have been committed while the post-commit hook was
|
||||||
|
# disabled.
|
||||||
|
require IkiWiki::Render;
|
||||||
|
refresh();
|
||||||
|
saveindex();
|
||||||
|
|
||||||
if (defined $conflict) {
|
if (defined $conflict) {
|
||||||
$form->field(name => "rcsinfo", value => rcs_prepedit($file),
|
$form->field(name => "rcsinfo", value => rcs_prepedit($file),
|
||||||
|
@ -546,22 +558,11 @@ sub cgi_editpage ($$) { #{{{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# Make sure that the repo is up-to-date;
|
|
||||||
# locking prevents the post-commit hook
|
|
||||||
# from updating it.
|
|
||||||
rcs_update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
require IkiWiki::Render;
|
|
||||||
refresh();
|
|
||||||
saveindex();
|
|
||||||
}
|
|
||||||
|
|
||||||
# The trailing question mark tries to avoid broken
|
# The trailing question mark tries to avoid broken
|
||||||
# caches and get the most recent version of the page.
|
# caches and get the most recent version of the page.
|
||||||
redirect($q, "$config{url}/".htmlpage($page)."?updated");
|
redirect($q, "$config{url}/".htmlpage($page)."?updated");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} #}}}
|
} #}}}
|
||||||
|
|
||||||
sub cgi_getsession ($) { #{{{
|
sub cgi_getsession ($) { #{{{
|
||||||
|
|
|
@ -125,17 +125,17 @@ sub cgi ($) { #{{{
|
||||||
IkiWiki::cgi_savesession($session);
|
IkiWiki::cgi_savesession($session);
|
||||||
$oldchoice=$session->param($choice_param);
|
$oldchoice=$session->param($choice_param);
|
||||||
if ($config{rcs}) {
|
if ($config{rcs}) {
|
||||||
# prevent deadlock with post-commit hook
|
disable_commit_hook();
|
||||||
IkiWiki::unlockwiki();
|
|
||||||
IkiWiki::rcs_commit($pagesources{$page}, "poll vote ($choice)",
|
IkiWiki::rcs_commit($pagesources{$page}, "poll vote ($choice)",
|
||||||
IkiWiki::rcs_prepedit($pagesources{$page}),
|
IkiWiki::rcs_prepedit($pagesources{$page}),
|
||||||
$session->param("name"), $ENV{REMOTE_ADDR});
|
$session->param("name"), $ENV{REMOTE_ADDR});
|
||||||
|
enable_commit_hook();
|
||||||
|
rcs_update();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
require IkiWiki::Render;
|
require IkiWiki::Render;
|
||||||
IkiWiki::refresh();
|
IkiWiki::refresh();
|
||||||
IkiWiki::saveindex();
|
IkiWiki::saveindex();
|
||||||
}
|
|
||||||
# Need to set cookie in same http response that does the
|
# Need to set cookie in same http response that does the
|
||||||
# redir.
|
# redir.
|
||||||
eval q{use CGI::Cookie};
|
eval q{use CGI::Cookie};
|
||||||
|
|
|
@ -36,6 +36,9 @@ sub setup_standard {
|
||||||
foreach my $wrapper (@wrappers) {
|
foreach my $wrapper (@wrappers) {
|
||||||
%config=(%startconfig, verbose => 0, %setup, %{$wrapper});
|
%config=(%startconfig, verbose => 0, %setup, %{$wrapper});
|
||||||
checkconfig();
|
checkconfig();
|
||||||
|
if (! $config{cgi} && ! $config{post_commit}) {
|
||||||
|
$config{post_commit}=1;
|
||||||
|
}
|
||||||
gen_wrapper();
|
gen_wrapper();
|
||||||
}
|
}
|
||||||
%config=(%startconfig);
|
%config=(%startconfig);
|
||||||
|
|
|
@ -27,8 +27,14 @@ ikiwiki (1.44) UNRELEASED; urgency=low
|
||||||
* Smarter detection of no-op changes to po files.
|
* Smarter detection of no-op changes to po files.
|
||||||
* Elegant patch from Ethan to clean up the display of page names in the
|
* Elegant patch from Ethan to clean up the display of page names in the
|
||||||
dropdown when creating a new page.
|
dropdown when creating a new page.
|
||||||
|
* Since the CGI had to drop the wiki lock to avoid deadlocking the
|
||||||
|
commit hook, it was possible for one CGI to race another one and "win"
|
||||||
|
the commit of both their files. This race has been fixed by adding a new
|
||||||
|
commitlock, which when locked by the CGI, disables the commit hook
|
||||||
|
(except for commit mails). The CGI then takes care of the updates the
|
||||||
|
commit hook would have done.
|
||||||
|
|
||||||
-- Joey Hess <joeyh@debian.org> Tue, 20 Feb 2007 19:14:39 -0500
|
-- Joey Hess <joeyh@debian.org> Wed, 21 Feb 2007 03:35:52 -0500
|
||||||
|
|
||||||
ikiwiki (1.43) unstable; urgency=low
|
ikiwiki (1.43) unstable; urgency=low
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,12 @@ sub main () { #{{{
|
||||||
require IkiWiki::Render;
|
require IkiWiki::Render;
|
||||||
commandline_render();
|
commandline_render();
|
||||||
}
|
}
|
||||||
|
elsif ($config{post_commit} && ! commit_hook_enabled()) {
|
||||||
|
if ($config{notify}) {
|
||||||
|
loadindex();
|
||||||
|
rcs_notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
lockwiki();
|
lockwiki();
|
||||||
loadindex();
|
loadindex();
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2007-02-20 19:07-0500\n"
|
"POT-Creation-Date: 2007-02-21 03:51-0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -41,16 +41,16 @@ msgstr ""
|
||||||
msgid "creating %s"
|
msgid "creating %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki/CGI.pm:483 ../IkiWiki/CGI.pm:511 ../IkiWiki/CGI.pm:544
|
#: ../IkiWiki/CGI.pm:483 ../IkiWiki/CGI.pm:511 ../IkiWiki/CGI.pm:556
|
||||||
#, perl-format
|
#, perl-format
|
||||||
msgid "editing %s"
|
msgid "editing %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki/CGI.pm:652
|
#: ../IkiWiki/CGI.pm:653
|
||||||
msgid "You are banned."
|
msgid "You are banned."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki/CGI.pm:684
|
#: ../IkiWiki/CGI.pm:685
|
||||||
msgid "login failed, perhaps you need to turn on cookies?"
|
msgid "login failed, perhaps you need to turn on cookies?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -380,15 +380,15 @@ msgstr ""
|
||||||
msgid "generating wrappers.."
|
msgid "generating wrappers.."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki/Setup/Standard.pm:68
|
#: ../IkiWiki/Setup/Standard.pm:71
|
||||||
msgid "rebuilding wiki.."
|
msgid "rebuilding wiki.."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki/Setup/Standard.pm:71
|
#: ../IkiWiki/Setup/Standard.pm:74
|
||||||
msgid "refreshing wiki.."
|
msgid "refreshing wiki.."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki/Setup/Standard.pm:80
|
#: ../IkiWiki/Setup/Standard.pm:83
|
||||||
msgid "done"
|
msgid "done"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -437,11 +437,11 @@ msgstr ""
|
||||||
msgid "usage: ikiwiki [options] source dest"
|
msgid "usage: ikiwiki [options] source dest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki.pm:103
|
#: ../IkiWiki.pm:104
|
||||||
msgid "Must specify url to wiki with --url when using --cgi"
|
msgid "Must specify url to wiki with --url when using --cgi"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../IkiWiki.pm:150 ../IkiWiki.pm:151
|
#: ../IkiWiki.pm:151 ../IkiWiki.pm:152
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -449,7 +449,7 @@ msgstr ""
|
||||||
#. translators: preprocessor directive name,
|
#. translators: preprocessor directive name,
|
||||||
#. translators: the second a page name, the
|
#. translators: the second a page name, the
|
||||||
#. translators: third a number.
|
#. translators: third a number.
|
||||||
#: ../IkiWiki.pm:560
|
#: ../IkiWiki.pm:561
|
||||||
#, perl-format
|
#, perl-format
|
||||||
msgid "%s preprocessing loop detected on %s at depth %i"
|
msgid "%s preprocessing loop detected on %s at depth %i"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
Loading…
Reference in New Issue