diff -r 740402e61479 roundup/cgi/client.py --- a/roundup/cgi/client.py Tue May 21 12:53:20 2013 -0700 +++ b/roundup/cgi/client.py Thu Dec 19 08:21:57 2013 -0800 @@ -548,6 +548,12 @@ # OpenSSL.SSL.SysCallError is similar to IOError above # may happen during write_html and serve_file, too. pass + except DetectorError as e: + if not self.instance.config.WEB_DEBUG: + self.send_error_to_admin(e.subject, e.html, e.txt) + self.write_html(self._(error_message)) + else: + self.write_html(e.html) except: # Something has gone badly wrong. Therefore, we should # make sure that the response code indicates failure. diff -r 740402e61479 roundup/cgi/exceptions.py --- a/roundup/cgi/exceptions.py Tue May 21 12:53:20 2013 -0700 +++ b/roundup/cgi/exceptions.py Thu Dec 19 08:21:57 2013 -0800 @@ -18,6 +18,14 @@ class NotModified(HTTPException): pass +class DetectorError(Exception): + """Raised when a detector throws an exception. +Contains details of the exception.""" + def __init__(self, subject, html, txt): + self.subject = subject + self.html = html + self.txt = txt + class FormError(ValueError): """An 'expected' exception occurred during form parsing. diff -r 740402e61479 roundup/hyperdb.py --- a/roundup/hyperdb.py Tue May 21 12:53:20 2013 -0700 +++ b/roundup/hyperdb.py Thu Dec 19 08:21:57 2013 -0800 @@ -21,12 +21,14 @@ __docformat__ = 'restructuredtext' # standard python modules -import os, re, shutil, weakref +import os, re, shutil, sys, weakref +import traceback # roundup modules import date, password from support import ensureParentsExist, PrioList, sorted, reversed from roundup.i18n import _ +from roundup.cgi.exceptions import DetectorError # # Types @@ -1251,7 +1253,16 @@ def fireAuditors(self, event, nodeid, newvalues): """Fire all registered auditors""" for prio, name, audit in self.auditors[event]: - audit(self.db, self, nodeid, newvalues) + try: + audit(self.db, self, nodeid, newvalues) + except Exception as e: + tb = traceback.format_exc() + html = ("

Traceback

" + str(tb).replace('\n', '
'). + replace(' ', ' ')) + txt = 'Caught exception %s: %s\n%s' % (str(type(e)), e, tb) + exc_info = sys.exc_info() + subject = "Error: %s" % exc_info[1] + raise DetectorError(subject, html, txt) def react(self, event, detector, priority = 100): """Register a reactor detector""" @@ -1260,7 +1271,16 @@ def fireReactors(self, event, nodeid, oldvalues): """Fire all registered reactors""" for prio, name, react in self.reactors[event]: - react(self.db, self, nodeid, oldvalues) + try: + react(self.db, self, nodeid, oldvalues) + except Exception as e: + tb = traceback.format_exc() + html = ("

Traceback

" + str(tb).replace('\n', '
'). + replace(' ', ' ')) + txt = 'Caught exception %s: %s\n%s' % (str(type(e)), e, tb) + exc_info = sys.exc_info() + subject = "Error: %s" % exc_info[1] + raise DetectorError(subject, html, txt) # # import / export support