https://github.com/python/cpython/commit/7134b407dc2d425a3e847555cde539c53adf9449 commit: 7134b407dc2d425a3e847555cde539c53adf9449 branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: savannahostrowski <[email protected]> date: 2025-12-17T19:48:18Z summary:
[3.14] GH-100964: Fix reference cycle in exhausted generator frames (GH-141112) (#142902) GH-100964: Fix reference cycle in exhausted generator frames (GH-141112) (cherry picked from commit 92243dc62ce10715ab0d9074b23dea5a1bfa9dcc) Co-authored-by: Savannah Ostrowski <[email protected]> files: A Misc/NEWS.d/next/Core_and_Builtins/2025-11-06-05-21-25.gh-issue-100964.TxPf1b.rst M Lib/test/test_generators.py M Python/ceval.c diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index b71c4d1c81951b..97f14314459a3c 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -134,6 +134,18 @@ def gen(): self.assertEqual(len(resurrected), 1) self.assertIsInstance(resurrected[0].gi_code, types.CodeType) + def test_exhausted_generator_frame_cycle(self): + def g(): + yield + + generator = g() + frame = generator.gi_frame + self.assertIsNone(frame.f_back) + next(generator) + self.assertIsNone(frame.f_back) + next(generator, None) + self.assertIsNone(frame.f_back) + class GeneratorTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-06-05-21-25.gh-issue-100964.TxPf1b.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-06-05-21-25.gh-issue-100964.TxPf1b.rst new file mode 100644 index 00000000000000..7c554cf8dda5d1 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-06-05-21-25.gh-issue-100964.TxPf1b.rst @@ -0,0 +1 @@ +Fix reference cycle in exhausted generator frames. Patch by Savannah Ostrowski. diff --git a/Python/ceval.c b/Python/ceval.c index faca6fe81b977a..87cf01730b472e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1920,9 +1920,9 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame) tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame); + frame->previous = NULL; _PyFrame_ClearExceptCode(frame); _PyErr_ClearExcState(&gen->gi_exc_state); - frame->previous = NULL; } void _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
