File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1313import inspect
1414import parser
1515
16- from test .support import captured_stderr
16+ from test .support import captured_stderr , disable_gc , gc_collect
1717
1818class TestPEP380Operation (unittest .TestCase ):
1919 """
@@ -954,6 +954,45 @@ def gen():
954954 list (gen ())
955955 self .assertEqual (ret , 42 )
956956
957+ def test_close_with_cleared_frame (self ):
958+ # See issue #17669.
959+ #
960+ # Create a stack of generators: outer() delegating to inner()
961+ # delegating to innermost(). The key point is that the instance of
962+ # inner is created first: this ensures that its frame appears before
963+ # the instance of outer in the GC linked list.
964+ #
965+ # At the gc.collect call:
966+ # - frame_clear is called on the inner_gen frame.
967+ # - gen_dealloc is called on the outer_gen generator (the only
968+ # reference is in the frame's locals).
969+ # - gen_close is called on the outer_gen generator.
970+ # - gen_close_iter is called to close the inner_gen generator, which
971+ # in turn calls gen_close, and gen_yf.
972+ #
973+ # Previously, gen_yf would crash since inner_gen's frame had been
974+ # cleared (and in particular f_stacktop was NULL).
975+
976+ def innermost ():
977+ yield
978+ def inner ():
979+ outer_gen = yield
980+ yield from innermost ()
981+ def outer ():
982+ inner_gen = yield
983+ yield from inner_gen
984+
985+ with disable_gc ():
986+ inner_gen = inner ()
987+ outer_gen = outer ()
988+ outer_gen .send (None )
989+ outer_gen .send (inner_gen )
990+ outer_gen .send (outer_gen )
991+
992+ del outer_gen
993+ del inner_gen
994+ gc_collect ()
995+
957996
958997def test_main ():
959998 from test import support
You can’t perform that action at this time.
0 commit comments