]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-100964: Break cycles involving exception state when returning from generator ...
authorMark Shannon <mark@hotpy.org>
Wed, 2 Aug 2023 17:44:20 +0000 (18:44 +0100)
committerGitHub <noreply@github.com>
Wed, 2 Aug 2023 17:44:20 +0000 (18:44 +0100)
Misc/NEWS.d/next/Core and Builtins/2023-07-30-18-05-11.gh-issue-100964.HluhBJ.rst [new file with mode: 0644]
Objects/genobject.c
Python/ceval.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-18-05-11.gh-issue-100964.HluhBJ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-30-18-05-11.gh-issue-100964.HluhBJ.rst
new file mode 100644 (file)
index 0000000..99ebc92
--- /dev/null
@@ -0,0 +1,2 @@
+Clear generators' exception state after ``return`` to break reference
+cycles.
index a630f84fb5a29d539ce3f48a3b13ea44e4b3e028..65782be182cd71680dc71983bc516cb340d03344 100644 (file)
@@ -149,14 +149,16 @@ gen_dealloc(PyGenObject *gen)
         gen->gi_frame_state = FRAME_CLEARED;
         frame->previous = NULL;
         _PyFrame_ClearExceptCode(frame);
+        _PyErr_ClearExcState(&gen->gi_exc_state);
     }
+    assert(gen->gi_exc_state.exc_value == NULL);
     if (_PyGen_GetCode(gen)->co_flags & CO_COROUTINE) {
         Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer);
     }
     Py_DECREF(_PyGen_GetCode(gen));
     Py_CLEAR(gen->gi_name);
     Py_CLEAR(gen->gi_qualname);
-    _PyErr_ClearExcState(&gen->gi_exc_state);
+
     PyObject_GC_Del(gen);
 }
 
@@ -252,10 +254,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
             !PyErr_ExceptionMatches(PyExc_StopAsyncIteration));
     }
 
-    /* generator can't be rerun, so release the frame */
-    /* first clean reference cycle through stored exception traceback */
-    _PyErr_ClearExcState(&gen->gi_exc_state);
-
+    assert(gen->gi_exc_state.exc_value == NULL);
     assert(gen->gi_frame_state == FRAME_CLEARED);
     *presult = result;
     return result ? PYGEN_RETURN : PYGEN_ERROR;
index 17818a0d3c17e642d0fe4b610dc091bc30fe4f52..369b9a69152a5c14613eb93040080bdf82f0dd2c 100644 (file)
@@ -1466,6 +1466,7 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
     tstate->c_recursion_remaining--;
     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
     _PyFrame_ClearExceptCode(frame);
+    _PyErr_ClearExcState(&gen->gi_exc_state);
     tstate->c_recursion_remaining++;
     frame->previous = NULL;
 }