From: Ben Darnell Date: Sun, 1 May 2011 19:55:08 +0000 (-0700) Subject: Run all IOStream callbacks via IOLoop.add_callback. X-Git-Tag: v2.0.0~92 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f8f3a9bf08f1cab1d2ab232074a14e7a94eaa4b1;p=thirdparty%2Ftornado.git Run all IOStream callbacks via IOLoop.add_callback. Closes #252 --- diff --git a/tornado/iostream.py b/tornado/iostream.py index 65f36edd8..02016a0f3 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -20,6 +20,7 @@ from __future__ import with_statement import collections import errno +import functools import logging import socket import sys @@ -222,23 +223,30 @@ class IOStream(object): self.close() raise - def _run_callback(self, callback, *args, **kwargs): - try: - # Use a NullContext to ensure that all StackContexts are run - # inside our blanket exception handler rather than outside. - with stack_context.NullContext(): - callback(*args, **kwargs) - except: - logging.error("Uncaught exception, closing connection.", - exc_info=True) - # Close the socket on an uncaught exception from a user callback - # (It would eventually get closed when the socket object is - # gc'd, but we don't want to rely on gc happening before we - # run out of file descriptors) - self.close() - # Re-raise the exception so that IOLoop.handle_callback_exception - # can see it and log the error - raise + def _run_callback(self, callback, *args): + def wrapper(): + try: + callback(*args) + except: + logging.error("Uncaught exception, closing connection.", + exc_info=True) + # Close the socket on an uncaught exception from a user callback + # (It would eventually get closed when the socket object is + # gc'd, but we don't want to rely on gc happening before we + # run out of file descriptors) + self.close() + # Re-raise the exception so that IOLoop.handle_callback_exception + # can see it and log the error + raise + # We schedule callbacks to be run on the next IOLoop iteration + # rather than running them directly for several reasons: + # * Prevents unbounded stack growth when a callback calls an + # IOLoop operation that immediately runs another callback + # * Provides a predictable execution context for e.g. + # non-reentrant mutexes + # * Ensures that the try/except in wrapper() is run outside + # of the application's StackContexts + self.io_loop.add_callback(wrapper) def _handle_read(self): while True: