Skip to content

Commit

Permalink
GH-100964: Break cycles involving exception state when returning from…
Browse files Browse the repository at this point in the history
… generator (GH-107563)
  • Loading branch information
markshannon authored Aug 2, 2023
1 parent dd693d6 commit 0d30a5a
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Clear generators' exception state after ``return`` to break reference
cycles.
9 changes: 4 additions & 5 deletions Objects/genobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit 0d30a5a

Please sign in to comment.