Mercurial > p > roundup > code
changeset 5079:65fef7858606
issue2550826 IOError in detector causes apache 'premature end of script headers' error
Capture all exceptions from auditors/reactors and raise a
DetectorError instead. This allows failures like IOErrors from the
detectors (e.g. unable to access files) to be handled. Previously an
IOError just resulted in no output (premature end of headers under
apache). Problem diagnosed and initial patch created by Tom Ekberg
(tekberg).
Patch application/mods and testing by rouilj.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Fri, 10 Jun 2016 23:33:11 -0400 |
| parents | 487dc55e3c5e |
| children | 89d69a822e5c |
| files | CHANGES.txt roundup/cgi/client.py roundup/cgi/exceptions.py roundup/hyperdb.py |
| diffstat | 4 files changed, 48 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Fri Jun 10 21:28:40 2016 -0400 +++ b/CHANGES.txt Fri Jun 10 23:33:11 2016 -0400 @@ -69,6 +69,13 @@ - issue2550907 Fix errors when creating documentation. Work done by Peter Funk (pefu). (Applied by John Rouillard with small change omitting obsolete security.txt.) +- issue2550826 Capture all exceptions from auditors/reactors and + raise a DetectorError instead. This allows failures like IOErrors + from the detectors (e.g. unable to access files) to be handled. + Previously an IOError just resulted in no output (premature end of + headers under apache). Problem diagnosed and initial patch created by + Tom Ekberg (tekberg). Further testing and patch change done by + John Rouillard. 2016-01-11: 1.5.1
--- a/roundup/cgi/client.py Fri Jun 10 21:28:40 2016 -0400 +++ b/roundup/cgi/client.py Fri Jun 10 23:33:11 2016 -0400 @@ -19,7 +19,7 @@ from roundup.exceptions import LoginError, Reject, RejectRaw, Unauthorised from roundup.cgi.exceptions import ( FormError, NotFound, NotModified, Redirect, SendFile, SendStaticFile, - SeriousError) + DetectorError, SeriousError) from roundup.cgi.form_parser import FormParser from roundup.mailer import Mailer, MessageSendError, encode_quopri from roundup.cgi import accept_language @@ -572,6 +572,15 @@ # 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: + # run when we are not in debug mode, so errors + # go to admin too. + self.send_error_to_admin(e.subject, e.html, e.txt) + self.write_html(e.html) + else: + # in debug mode, only write error to screen. + self.write_html(e.html) except: # Something has gone badly wrong. Therefore, we should # make sure that the response code indicates failure.
--- a/roundup/cgi/exceptions.py Fri Jun 10 21:28:40 2016 -0400 +++ b/roundup/cgi/exceptions.py Fri Jun 10 23:33:11 2016 -0400 @@ -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.
--- a/roundup/hyperdb.py Fri Jun 10 21:28:40 2016 -0400 +++ b/roundup/hyperdb.py Fri Jun 10 23:33:11 2016 -0400 @@ -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 from roundup.i18n import _ +from roundup.cgi.exceptions import DetectorError # # Types @@ -1290,7 +1292,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 = ("<h1>Traceback</h1>" + str(tb).replace('\n', '<br>'). + 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""" @@ -1299,7 +1310,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 = ("<h1>Traceback</h1>" + str(tb).replace('\n', '<br>'). + 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
