From: Ben Darnell Date: Sun, 12 May 2013 23:32:20 +0000 (-0400) Subject: Don't try sending another error response in _handle_request_exception X-Git-Tag: v3.1.0~76^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c47e5d5df0ea99935a6598323a2f8ad1e69a5e5;p=thirdparty%2Ftornado.git Don't try sending another error response in _handle_request_exception if the stack context catches an error after the request is done. (this may be related to the error discussed in the comments of #751) --- diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index a7f89620d..5e813e5d0 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -1250,3 +1250,31 @@ class GetArgumentErrorTest(SimpleHandlerTestCase): self.assertEqual(json_decode(response.body), {'arg_name': 'foo', 'log_message': 'Missing argument foo'}) + + +class MultipleExceptionTest(SimpleHandlerTestCase): + class Handler(RequestHandler): + exc_count = 0 + + @asynchronous + def get(self): + from tornado.ioloop import IOLoop + IOLoop.current().add_callback(lambda: 1 / 0) + IOLoop.current().add_callback(lambda: 1 / 0) + + def log_exception(self, typ, value, tb): + MultipleExceptionTest.Handler.exc_count += 1 + + def test_multi_exception(self): + # This test verifies that multiple exceptions raised into the same + # ExceptionStackContext do not generate extraneous log entries + # due to "Cannot send error response after headers written". + # log_exception is called, but it does not proceed to send_error. + response = self.fetch('/') + self.assertEqual(response.code, 500) + response = self.fetch('/') + self.assertEqual(response.code, 500) + # Each of our two requests generated two exceptions, we should have + # seen at least three of them by now (the fourth may still be + # in the queue). + self.assertGreater(MultipleExceptionTest.Handler.exc_count, 2) diff --git a/tornado/web.py b/tornado/web.py index 7bc715d7e..dfa357c00 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -1113,6 +1113,11 @@ class RequestHandler(object): def _handle_request_exception(self, e): self.log_exception(*sys.exc_info()) + if self._finished: + # Extra errors after the request has been finished should + # be logged, but there is no reason to continue to try and + # send a response. + return if isinstance(e, HTTPError): if e.status_code not in httputil.responses and not e.reason: gen_log.error("Bad HTTP status code: %d", e.status_code)