diff options
author | Benjamin Peterson <benjamin@python.org> | 2013-07-27 21:06:56 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2013-07-27 21:06:56 (GMT) |
commit | d979c72160025d7163e5d75eb4e676bfaedfea20 (patch) | |
tree | d8b768b30f66c6d4fd07a0decdd1c389dcf791c5 /Lib/test | |
parent | 9eda66da785cc11dc7e84027990e3108e5aec433 (diff) | |
download | cpython-d979c72160025d7163e5d75eb4e676bfaedfea20.zip cpython-d979c72160025d7163e5d75eb4e676bfaedfea20.tar.gz cpython-d979c72160025d7163e5d75eb4e676bfaedfea20.tar.bz2 |
add a test for issue #17669 (closes #18565)
Patch from Phil Connell.
Diffstat (limited to 'Lib/test')
-rw-r--r-- | 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 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 |