add a test for issue #17669 (closes #18565)

Patch from Phil Connell.
This commit is contained in:
Benjamin Peterson 2013-07-27 14:06:56 -07:00
parent 9eda66da78
commit d979c72160
1 changed files with 40 additions and 1 deletions

View File

@ -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