bpo-20526: Fix PyThreadState_Clear(): don't decref frame (GH-19120) (… · python/cpython@d1c0989 (original) (raw)

File tree

3 files changed

lines changed

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -216,6 +216,7 @@ typedef struct _ts {
216 216 struct _ts *next;
217 217 PyInterpreterState *interp;
218 218
219 +/* Borrowed reference to the current frame (it can be NULL) */
219 220 struct _frame *frame;
220 221 int recursion_depth;
221 222 char overflowed; /* The stack has overflowed. Allow 50 more calls
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 +Fix :c:func:`PyThreadState_Clear()`. ``PyThreadState.frame`` is a borrowed
2 +reference, not a strong reference: ``PyThreadState_Clear()`` must not call
3 +``Py_CLEAR(tstate->frame)``.
Original file line number Diff line number Diff line change
@@ -566,11 +566,19 @@ _PyState_ClearModules(void)
566 566 void
567 567 PyThreadState_Clear(PyThreadState *tstate)
568 568 {
569 -if (Py_VerboseFlag && tstate->frame != NULL)
569 +if (Py_VerboseFlag && tstate->frame != NULL) {
570 +/* bpo-20526: After the main thread calls
571 + _PyRuntimeState_SetFinalizing() in Py_FinalizeEx(), threads must
572 + exit when trying to take the GIL. If a thread exit in the middle of
573 + _PyEval_EvalFrameDefault(), tstate->frame is not reset to its
574 + previous value. It is more likely with daemon threads, but it can
575 + happen with regular threads if threading._shutdown() fails
576 + (ex: interrupted by CTRL+C). */
570 577 fprintf(stderr,
571 578 "PyThreadState_Clear: warning: thread still has a frame\n");
579 + }
572 580
573 -Py_CLEAR(tstate->frame);
581 +/* Don't clear tstate->frame: it is a borrowed reference */
574 582
575 583 Py_CLEAR(tstate->dict);
576 584 Py_CLEAR(tstate->async_exc);