summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbwarsaw2001-05-03 21:20:39 +0000
committerbwarsaw2001-05-03 21:20:39 +0000
commite57c5809ef1243cf296fa34d1a1649fa5e2c77ec (patch)
treea51b78b9be7f1ea93aa10b6d6d41c7b87b8f19fd
parentc1c4b2883c941def86fd714958b649524973cd34 (diff)
downloadmailman-e57c5809ef1243cf296fa34d1a1649fa5e2c77ec.tar.gz
mailman-e57c5809ef1243cf296fa34d1a1649fa5e2c77ec.tar.zst
mailman-e57c5809ef1243cf296fa34d1a1649fa5e2c77ec.zip
Be more paranoid about abnormal shutdown conditions, specifically:
main(): When the user hits the stop button on their browser during a long running operation, Apache 1.3/mod_cgi will eventually catch a SIGPIPE when output is written to the client. It then turns around and SIGTERMs the cgi process, waits three seconds, then SIGKILLs the cgi process. This patch fixes the stale lock file that can result under this situation. Since Python by default doesn't catch SIGTERM, and SIGKILL is uncatchable, either signal would cause the cgi process to exit without raising an exception, giving no chance for the script to clean up after itself. We now open the MailList object in two phases: first, open it unlocked, then lock it and install a SIGTERM handler. The SIGTERM handler unlocks the list and exits, aborting any changes that may have taken place. This is the safest way to ensure that stale locks won't be left around causing other hits on the list to become wedged for a long time.
-rw-r--r--Mailman/Cgi/subscribe.py25
1 files changed, 23 insertions, 2 deletions
diff --git a/Mailman/Cgi/subscribe.py b/Mailman/Cgi/subscribe.py
index 5f11c0fd0..b0c398fc6 100644
--- a/Mailman/Cgi/subscribe.py
+++ b/Mailman/Cgi/subscribe.py
@@ -19,6 +19,7 @@
import sys
import os
import cgi
+import signal
from Mailman import mm_cfg
from Mailman import Utils
@@ -49,7 +50,7 @@ def main():
listname = parts[0].lower()
try:
- mlist = MailList.MailList(listname)
+ mlist = MailList.MailList(listname, lock=0)
except Errors.MMListError, e:
doc.AddItem(Header(2, _("Error")))
doc.AddItem(Bold(_('No such list <em>%(listname)s</em>')))
@@ -68,10 +69,30 @@ def main():
i18n.set_language(language)
doc.set_language(language)
+ # We need a signal handler to catch the SIGTERM that can come from Apache
+ # when the user hits the browser's STOP button. See the comment in
+ # admin.py for details.
+ #
+ # BAW: Strictly speaking, the list should not need to be locked just to
+ # read the request database. However the request database asserts that
+ # the list is locked in order to load it and it's not worth complicating
+ # that logic.
+ def sigterm_handler(signum, frame, mlist=mlist):
+ # Make sure the list gets unlocked...
+ mlist.Unlock()
+ # ...and ensure we exit, otherwise race conditions could cause us to
+ # enter MailList.Save() while we're in the unlocked state, and that
+ # could be bad!
+ sys.exit(0)
+
+ mlist.Lock()
try:
+ # Install the emergency shutdown signal handler
+ signal.signal(signal.SIGTERM, sigterm_handler)
+
process_form(mlist, doc, cgidata, language)
- finally:
mlist.Save()
+ finally:
mlist.Unlock()