summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2013-07-27 21:07:19 (GMT)
committerBenjamin Peterson <benjamin@python.org>2013-07-27 21:07:19 (GMT)
commit290371dadc215770bbea1d84e6e9c1d93f155a0e (patch)
tree0ccc1fa67fea1d2b87338a8270bb95443e9e7b17 /Lib/test
parent937b50c378d7025a1242d4867a0376e48239f049 (diff)
parentd979c72160025d7163e5d75eb4e676bfaedfea20 (diff)
downloadcpython-290371dadc215770bbea1d84e6e9c1d93f155a0e.zip
cpython-290371dadc215770bbea1d84e6e9c1d93f155a0e.tar.gz
cpython-290371dadc215770bbea1d84e6e9c1d93f155a0e.tar.bz2
merge 3.3 (#18565)
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_pep380.py41
1 files changed, 40 insertions, 1 deletions
diff --git a/Lib/test/test_pep380.py b/Lib/test/test_pep380.py
index f3eed43..4a43b7d 100644
--- a/Lib/test/test_pep380.py
+++ b/Lib/test/test_pep380.py
@@ -13,7 +13,7 @@ import sys
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 @@ class TestPEP380Operation(unittest.TestCase):
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