]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] GH-100964: Fix reference cycle in exhausted generator frames (G… (#142904)
authorSavannah Ostrowski <savannah@python.org>
Wed, 17 Dec 2025 20:04:53 +0000 (12:04 -0800)
committerGitHub <noreply@github.com>
Wed, 17 Dec 2025 20:04:53 +0000 (20:04 +0000)
* [3.13] GH-100964: Fix reference cycle in exhausted generator frames (GH-141112)
(cherry picked from commit 92243dc62ce10715ab0d9074b23dea5a1bfa9dcc)

Co-authored-by: Savannah Ostrowski <savannah@python.org>
Lib/test/test_generators.py
Misc/NEWS.d/next/Core and Builtins/2025-11-06-05-21-25.gh-issue-100964.TxPf1b.rst [new file with mode: 0644]
Python/ceval.c

index d6014fd9d63cdf269188ceffed8a58b7d618c2d2..7aa4458fc71a5ebca3df825f3a5b4c97dcf0ed62 100644 (file)
@@ -112,6 +112,18 @@ class FinalizationTest(unittest.TestCase):
                 gen.send(2)
             self.assertEqual(cm.exception.value, 2)
 
+    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 (file)
index 0000000..7c554cf
--- /dev/null
@@ -0,0 +1 @@
+Fix reference cycle in exhausted generator frames. Patch by Savannah Ostrowski.
index 0be6c57c1cf1ddabd5945877f09d3145f2ac1239..301cc3b2b90358c42f61c35fe1db394eb891bc1d 100644 (file)
@@ -1696,10 +1696,10 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
     gen->gi_exc_state.previous_item = NULL;
     tstate->c_recursion_remaining--;
     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
+    frame->previous = NULL;
     _PyFrame_ClearExceptCode(frame);
     _PyErr_ClearExcState(&gen->gi_exc_state);
     tstate->c_recursion_remaining++;
-    frame->previous = NULL;
 }
 
 void