From: Ben Darnell Date: Sun, 20 Jan 2013 16:39:18 +0000 (-0500) Subject: Fix memory leak with gen.engine, RequestHandler.flush, and closed connections. X-Git-Tag: v3.0.0~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=769bc52e11656788782a6e7a922ef646503f9ab0;p=thirdparty%2Ftornado.git Fix memory leak with gen.engine, RequestHandler.flush, and closed connections. This was unfortunately difficult to reproduce in a unit test, even though the test program attached to bug 660 easily reproduces it. Closes #660. --- diff --git a/tornado/httpserver.py b/tornado/httpserver.py index 1781589fd..11ac8a9c2 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -186,6 +186,18 @@ class HTTPConnection(object): self._header_callback = stack_context.wrap(self._on_headers) self.stream.read_until(b"\r\n\r\n", self._header_callback) self._write_callback = None + self._close_callback = None + + def set_close_callback(self, callback): + self._close_callback = stack_context.wrap(callback) + self.stream.set_close_callback(self._on_connection_close) + + def _on_connection_close(self): + callback = self._close_callback + self._close_callback = None + callback() + # Delete any unfinished callbacks to break up reference cycles. + self._write_callback = None def close(self): self.stream.close() diff --git a/tornado/iostream.py b/tornado/iostream.py index db7ce4aa0..d98136ea4 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -242,6 +242,8 @@ class BaseIOStream(object): cb = self._close_callback self._close_callback = None self._run_callback(cb) + # Delete any unfinished callbacks to break up reference cycles. + self._read_callback = self._write_callback = None def reading(self): """Returns true if we are currently reading from the stream.""" diff --git a/tornado/web.py b/tornado/web.py index 72ab9d3ae..7fd0c208d 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -141,7 +141,7 @@ class RequestHandler(object): self.clear() # Check since connection is not available in WSGI if getattr(self.request, "connection", None): - self.request.connection.stream.set_close_callback( + self.request.connection.set_close_callback( self.on_connection_close) self.initialize(**kwargs) diff --git a/website/sphinx/releases/next.rst b/website/sphinx/releases/next.rst index 430584fb6..1380b0f4f 100644 --- a/website/sphinx/releases/next.rst +++ b/website/sphinx/releases/next.rst @@ -210,3 +210,8 @@ In progress * Python 2.5 is no longer supported. * Installation under Python 3 no longer uses ``2to3``. * `tornado.util.b` (which was only intended for internal use) is gone. +* Fixed a memory leak involving ``gen.engine``, `RequestHandler.flush`, + and clients closing connections while output is being written. +* `tornado.httpserver.HTTPConnection` now has a `set_close_callback` + method that should be used instead of reaching into its ``stream`` + attribute.