]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Fix memory leak with gen.engine, RequestHandler.flush, and closed connections.
authorBen Darnell <ben@bendarnell.com>
Sun, 20 Jan 2013 16:39:18 +0000 (11:39 -0500)
committerBen Darnell <ben@bendarnell.com>
Sun, 20 Jan 2013 16:39:18 +0000 (11:39 -0500)
This was unfortunately difficult to reproduce in a unit test, even though
the test program attached to bug 660 easily reproduces it.

Closes #660.

tornado/httpserver.py
tornado/iostream.py
tornado/web.py
website/sphinx/releases/next.rst

index 1781589fdcaee7c27b6b5370396b8060e652a4b5..11ac8a9c2a1621c7f4c307ece88ddb3762f043d9 100644 (file)
@@ -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()
index db7ce4aa0e25febae27e0cecc6ac3c1ec3a52052..d98136ea40e57b2e6294e32e104773069e04f64b 100644 (file)
@@ -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."""
index 72ab9d3ae8e3969fdc44d05a6e69a58fdcddba53..7fd0c208dee1a05518d93da1116b84c6e24203d9 100644 (file)
@@ -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)
 
index 430584fb6789fe5af5e7878945f42153fdfa5580..1380b0f4fe5cdffa5aaf15b415322a2f4a64bef2 100644 (file)
@@ -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.