[Python-checkins] cpython (3.3): add a test for issue #17669 (closes #18565)

benjamin.peterson python-checkins at python.org
Sat Jul 27 23:07:39 CEST 2013


http://hg.python.org/cpython/rev/516303f32bad
changeset:   84868:516303f32bad
branch:      3.3
parent:      84866:55dcf9e065be
user:        Benjamin Peterson <benjamin at python.org>
date:        Sat Jul 27 14:06:56 2013 -0700
summary:
  add a test for issue #17669 (closes #18565)

Patch from Phil Connell.

files:
  Lib/test/test_pep380.py |  41 ++++++++++++++++++++++++++++-
  1 files changed, 40 insertions(+), 1 deletions(-)


diff --git a/Lib/test/test_pep380.py b/Lib/test/test_pep380.py
--- a/Lib/test/test_pep380.py
+++ b/Lib/test/test_pep380.py
@@ -13,7 +13,7 @@
 import inspect
 import parser
 
-from test.support import captured_stderr
+from test.support import captured_stderr, disable_gc, gc_collect
 
 class TestPEP380Operation(unittest.TestCase):
     """
@@ -954,6 +954,45 @@
         list(gen())
         self.assertEqual(ret, 42)
 
+    def test_close_with_cleared_frame(self):
+        # See issue #17669.
+        #
+        # Create a stack of generators: outer() delegating to inner()
+        # delegating to innermost(). The key point is that the instance of
+        # inner is created first: this ensures that its frame appears before
+        # the instance of outer in the GC linked list.
+        #
+        # At the gc.collect call:
+        #   - frame_clear is called on the inner_gen frame.
+        #   - gen_dealloc is called on the outer_gen generator (the only
+        #     reference is in the frame's locals).
+        #   - gen_close is called on the outer_gen generator.
+        #   - gen_close_iter is called to close the inner_gen generator, which
+        #     in turn calls gen_close, and gen_yf.
+        #
+        # Previously, gen_yf would crash since inner_gen's frame had been
+        # cleared (and in particular f_stacktop was NULL).
+
+        def innermost():
+            yield
+        def inner():
+            outer_gen = yield
+            yield from innermost()
+        def outer():
+            inner_gen = yield
+            yield from inner_gen
+
+        with disable_gc():
+            inner_gen = inner()
+            outer_gen = outer()
+            outer_gen.send(None)
+            outer_gen.send(inner_gen)
+            outer_gen.send(outer_gen)
+
+            del outer_gen
+            del inner_gen
+            gc_collect()
+
 
 def test_main():
     from test import support

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list