8000 GH-100964: Break cycles involving exception state when returning from… · python/cpython@0d30a5a · GitHub
[go: up one dir, main page]

Skip to content

Commit 0d30a5a

Browse files
authored
GH-100964: Break cycles involving exception state when returning from generator (GH-107563)
1 parent dd693d6 commit 0d30a5a

File tree

3 files changed

+7
-5
lines changed

3 files changed

+7
-5
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Clear generators' exception state after ``return`` to break reference
2+
cycles.

Objects/genobject.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,16 @@ gen_dealloc(PyGenObject *gen)
149149
gen->gi_frame_state = FRAME_CLEARED;
150150
frame->previous = NULL;
151151
_PyFrame_ClearExceptCode(frame);
152+
_PyErr_ClearExcState(&gen->gi_exc_state);
152153
}
154+
assert(gen->gi_exc_state.exc_value == NULL);
153155
if (_PyGen_GetCode(gen)->co_flags & CO_COROUTINE) {
154156
Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer);
155157
}
156158
Py_DECREF(_PyGen_GetCode(gen));
157159
Py_CLEAR(gen->gi_name);
158160
Py_CLEAR(gen->gi_qualname);
159-
_PyErr_ClearExcState(&gen->gi_exc_state);
161+
160162
PyObject_GC_Del(gen);
161163
}
162164

@@ -252,10 +254,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
252254
!PyErr_ExceptionMatches(PyExc_StopAsyncIteration));
253255
}
254256

255-
/* generator can't be rerun, so release the frame */
256-
/* first clean reference cycle through stored exception traceback */
257-
_PyErr_ClearExcState(&gen->gi_exc_state);
258-
257+
assert(gen->gi_exc_state.exc_value == NULL);
259258
assert(gen->gi_frame_state == FRAME_CLEARED);
260259
*presult = result;
261260
return result ? PYGEN_RETURN : PYGEN_ERROR;

Python/ceval.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,6 +1466,7 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
14661466
tstate->c_recursion_remaining--;
14671467
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
14681468
_PyFrame_ClearExceptCode(frame);
1469+
_PyErr_ClearExcState(&gen->gi_exc_state);
14691470
tstate->c_recursion_remaining++;
14701471
frame->previous = NULL;
14711472
}

0 commit comments

Comments
 (0)
0