Mark Sapiro wrote:
>Thus, I have modified the previous
>suggested patch, and a new patch is attached which catches any
>exception from switchboard.dequeue() and logs and preserves the queue
>entry.


Ooops! It's attached this time.

-- 
Mark Sapiro <[EMAIL PROTECTED]>       The highway is for gamblers,
San Francisco Bay Area, California    better use your sense - B. Dylan

Index: Runner.py
===================================================================
--- Runner.py   (revision 8147)
+++ Runner.py   (working copy)
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2006 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2007 by the Free Software Foundation, Inc.
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -98,16 +98,17 @@
                 # Ask the switchboard for the message and metadata objects
                 # associated with this filebase.
                 msg, msgdata = self._switchboard.dequeue(filebase)
-            except email.Errors.MessageParseError, e:
-                # It's possible to get here if the message was stored in the
-                # pickle in plain text, and the metadata had a _parsemsg key
-                # that was true, /and/ if the message had some bogosity in
-                # it.  It's almost always going to be spam or bounced spam.
-                # There's not much we can do (and we didn't even get the
-                # metadata, so just log the exception and continue.
+            except Exception, e:
+                # This used to just catch email.Errors.MessageParseError,
+                # but other problems can occur in message parsing, e.g.
+                # ValueError, and exceptions can occur in unpickling too.
+                # We don't want the runner to die, so we just log and skip
+                # this entry, but preserve it for analysis.
                 self._log(e)
-                syslog('error', 'Ignoring unparseable message: %s', filebase)
-                self._switchboard.finish(filebase)
+                syslog('error',
+                       'Skipping and preserving unparseable message: %s',
+                       filebase)
+                self._switchboard.finish(filebase, preserve=True)
                 continue
             try:
                 self._onefile(msg, msgdata)
@@ -122,9 +123,22 @@
                 self._log(e)
                 # Put a marker in the metadata for unshunting
                 msgdata['whichq'] = self._switchboard.whichq()
-                new_filebase = self._shunt.enqueue(msg, msgdata)
-                syslog('error', 'SHUNTING: %s', new_filebase)
-                self._switchboard.finish(filebase)
+                # It is possible that shunting can throw an exception, e.g. a
+                # permissions problem or a MemoryError due to a really large
+                # message.  Try to be graceful.
+                try:
+                    new_filebase = self._shunt.enqueue(msg, msgdata)
+                    syslog('error', 'SHUNTING: %s', new_filebase)
+                    self._switchboard.finish(filebase)
+                except Exception, e:
+                    # The message wasn't successfully shunted.  Log the
+                    # exception and try to preserve the original queue entry
+                    # for possible analysis.
+                    self._log(e)
+                    syslog('error',
+                           'SHUNTING FAILED, preserving original entry: %s',
+                           filebase)
+                    self._switchboard.finish(filebase, preserve=True)
             # Other work we want to do each time through the loop
             Utils.reap(self._kids, once=True)
             self._doperiodic()
Index: Switchboard.py
===================================================================
--- Switchboard.py      (revision 8147)
+++ Switchboard.py      (working copy)
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2006 by the Free Software Foundation, Inc.
+# Copyright (C) 2001-2007 by the Free Software Foundation, Inc.
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -164,12 +164,22 @@
             msg = email.message_from_string(msg, Message.Message)
         return msg, data
 
-    def finish(self, filebase):
+    def finish(self, filebase, preserve=False):
         bakfile = os.path.join(self.__whichq, filebase + '.bak')
         try:
-            os.unlink(bakfile)
+            if preserve:
+                psvfile = os.path.join(self.__whichq, filebase + '.psv')
+                # Should this be
+                # psvfile = os.path.join(mm_cfg.SHUNTQUEUE_DIR, filebase + 
'.psv')
+                # or
+                # psvfile = os.path.join(mm_cfg.BADQUEUE_DIR, filebase + 
'.psv')
+                # If so, we need to consider the queue directory not existing.
+                os.rename(bakfile, psvfile)
+            else:
+                os.unlink(bakfile)
         except EnvironmentError, e:
-            syslog('error', 'Failed to unlink backup file: %s', bakfile)
+            syslog('error', 'Failed to unlink/preserve backup file: %s',
+                   bakfile)
 
     def files(self, extension='.pck'):
         times = {}
_______________________________________________
Mailman-Developers mailing list
[email protected]
http://mail.python.org/mailman/listinfo/mailman-developers
Mailman FAQ: http://www.python.org/cgi-bin/faqw-mm.py
Searchable Archives: 
http://www.mail-archive.com/mailman-developers%40python.org/
Unsubscribe: 
http://mail.python.org/mailman/options/mailman-developers/archive%40jab.org

Security Policy: 
http://www.python.org/cgi-bin/faqw-mm.py?req=show&file=faq01.027.htp

Reply via email to