Commit d979c721 authored by Benjamin Peterson's avatar Benjamin Peterson

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

Patch from Phil Connell.
parent 9eda66da
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment