]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Remove reference to last task and his arguments in engine to free memory.
authorhomm <homm86@gmail.com>
Sun, 28 Apr 2013 17:35:48 +0000 (21:35 +0400)
committerhomm <homm86@gmail.com>
Sun, 28 Apr 2013 17:35:48 +0000 (21:35 +0400)
tornado/gen.py
tornado/test/gen_test.py

index 938fef61b4d7a59725c45f7bf7adb7ce15f50a9f..7f8de1284f24bee1866ec0dd517601c250bd977d 100644 (file)
@@ -439,6 +439,9 @@ class _NullYieldPoint(YieldPoint):
         return None
 
 
+_null_yield_point = _NullYieldPoint()
+
+
 class Runner(object):
     """Internal implementation of `tornado.gen.engine`.
 
@@ -449,7 +452,7 @@ class Runner(object):
     def __init__(self, gen, final_callback):
         self.gen = gen
         self.final_callback = final_callback
-        self.yield_point = _NullYieldPoint()
+        self.yield_point = _null_yield_point
         self.pending_callbacks = set()
         self.results = {}
         self.running = False
@@ -505,6 +508,7 @@ class Runner(object):
                         yielded = self.gen.send(next)
                 except (StopIteration, Return) as e:
                     self.finished = True
+                    self.yield_point = _null_yield_point
                     if self.pending_callbacks and not self.had_exception:
                         # If we ran cleanly without waiting on all callbacks
                         # raise an error (really more of a warning).  If we
@@ -518,6 +522,7 @@ class Runner(object):
                     return
                 except Exception:
                     self.finished = True
+                    self.yield_point = _null_yield_point
                     raise
                 if isinstance(yielded, list):
                     yielded = Multi(yielded)
index d77297dbf850bc44e700cfad65cb492d9fa28fd5..ae2461e577a147b20f9921adb92ee305edeed5ad 100644 (file)
@@ -5,6 +5,7 @@ import functools
 import sys
 import textwrap
 import time
+import platform
 
 from tornado.concurrent import return_future
 from tornado.escape import url_escape
@@ -19,6 +20,8 @@ from tornado import gen
 
 
 skipBefore33 = unittest.skipIf(sys.version_info < (3, 3), 'PEP 380 not available')
+skipNotCPython = unittest.skipIf(platform.python_implementation() != 'CPython',
+                                'Not CPython implementation')
 
 
 class GenEngineTest(AsyncTestCase):
@@ -488,6 +491,24 @@ class GenEngineTest(AsyncTestCase):
         with self.assertRaises(gen.ReturnValueIgnoredError):
             self.run_gen(f)
 
+    @skipNotCPython
+    def test_task_refcounting(self):
+        # Task with arguments on CPython should be relased immediately after
+        # engine stop. And should not be delayed to garbage collection.
+        class Task(gen.Task):
+            "Task class which count self instances release."
+            relased = 0
+            def __del__(self):
+                type(self).relased += 1
+
+        @gen.engine
+        def f():
+            yield Task(lambda _arg, callback: callback(), Task(None))
+            self.stop()
+
+        self.run_gen(f)
+        self.assertEqual(Task.relased, 2)
+
 
 class GenCoroutineTest(AsyncTestCase):
     def setUp(self):