Skip to content

Commit 2f74848

Browse files
Make sure we make *all* pending calls when finishing.
1 parent 55f9b47 commit 2f74848

1 file changed

Lines changed: 25 additions & 6 deletions

File tree

Python/ceval_gil.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -971,12 +971,31 @@ _Py_FinishPendingCalls(PyThreadState *tstate)
971971
assert(PyGILState_Check());
972972
assert(_PyThreadState_CheckConsistency(tstate));
973973

974-
if (make_pending_calls(tstate) < 0) {
975-
PyObject *exc = _PyErr_GetRaisedException(tstate);
976-
PyErr_BadInternalCall();
977-
_PyErr_ChainExceptions1(exc);
978-
_PyErr_Print(tstate);
979-
}
974+
struct _pending_calls *pending = &tstate->interp->ceval.pending;
975+
struct _pending_calls *pending_main =
976+
_Py_IsMainThread() && _Py_IsMainInterpreter(tstate->interp)
977+
? &_PyRuntime.ceval.pending_mainthread
978+
: NULL;
979+
/* make_pending_calls() may return early without making all pending
980+
calls, so we keep trying until we're actually done. */
981+
int32_t npending = INT32_MAX;
982+
int32_t npending_prev = -1;
983+
do {
984+
assert(npending_prev < 0 || npending_prev > npending);
985+
npending_prev = npending;
986+
987+
if (make_pending_calls(tstate) < 0) {
988+
PyObject *exc = _PyErr_GetRaisedException(tstate);
989+
PyErr_BadInternalCall();
990+
_PyErr_ChainExceptions1(exc);
991+
_PyErr_Print(tstate);
992+
}
993+
994+
npending = _Py_atomic_load_int32_relaxed(&pending->npending);
995+
if (pending_main != NULL) {
996+
npending += _Py_atomic_load_int32_relaxed(&pending_main->npending);
997+
}
998+
} while (npending > 0);
980999
}
9811000

9821001
int

0 commit comments

Comments
 (0)