summaryrefslogtreecommitdiff
path: root/Mailman
diff options
context:
space:
mode:
authorbwarsaw2001-05-03 21:19:42 +0000
committerbwarsaw2001-05-03 21:19:42 +0000
commit6aa9a8f9bbf8bfe7452e283f338dfc63b9c765fe (patch)
tree0bb1f350d30f82f9dbcd5b0c414b3830a47a4e1b /Mailman
parentcb15f13431e8433eda8b25b178e3b48b1b02de36 (diff)
downloadmailman-6aa9a8f9bbf8bfe7452e283f338dfc63b9c765fe.tar.gz
mailman-6aa9a8f9bbf8bfe7452e283f338dfc63b9c765fe.tar.zst
mailman-6aa9a8f9bbf8bfe7452e283f338dfc63b9c765fe.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. Also, de-string-modulification.
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Cgi/handle_opts.py28
1 files changed, 24 insertions, 4 deletions
diff --git a/Mailman/Cgi/handle_opts.py b/Mailman/Cgi/handle_opts.py
index d065b0d8e..0592f961d 100644
--- a/Mailman/Cgi/handle_opts.py
+++ b/Mailman/Cgi/handle_opts.py
@@ -18,8 +18,8 @@
import sys
import os
-import string
import cgi
+import signal
from Mailman import mm_cfg
from Mailman import Utils
@@ -60,11 +60,11 @@ def main():
print doc.Format(bgcolor="#ffffff")
return
- listname = string.lower(parts[0])
+ listname = parts[0].lower()
user = parts[1]
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>')))
@@ -72,10 +72,30 @@ def main():
syslog('error', 'No such list "%s": %s\n' % (listname, e))
return
+ # 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, user, doc)
- finally:
mlist.Save()
+ finally:
mlist.Unlock()