diff options
| author | bwarsaw | 2001-05-03 21:19:42 +0000 |
|---|---|---|
| committer | bwarsaw | 2001-05-03 21:19:42 +0000 |
| commit | 6aa9a8f9bbf8bfe7452e283f338dfc63b9c765fe (patch) | |
| tree | 0bb1f350d30f82f9dbcd5b0c414b3830a47a4e1b /Mailman | |
| parent | cb15f13431e8433eda8b25b178e3b48b1b02de36 (diff) | |
| download | mailman-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.py | 28 |
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() |
