Skip to content

Commit 54cc326

Browse files
Prevent adding pending calls if finalizing.
1 parent 1160c4d commit 54cc326

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

Include/internal/pycore_pystate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct _is {
3232
int64_t id_refcount;
3333
PyThread_type_lock id_mutex;
3434

35+
int finalizing;
36+
3537
PyObject *modules;
3638
PyObject *modules_by_index;
3739
PyObject *sysdict;

Python/ceval.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,21 @@ _Py_AddPendingCall(PyInterpreterState *interp, int (*func)(void *), void *arg)
386386
return -1;
387387
}
388388

389-
int result = _add_pending_call(interp, func, arg);
389+
int result = -1;
390+
if (interp->finalizing) {
391+
PyObject *exc, *val, *tb;
392+
PyErr_Fetch(&exc, &val, &tb);
393+
PyErr_SetString(PyExc_SystemError, "Py_AddPendingCall: cannot add pending calls (interpreter shutting down)");
394+
PyErr_Print();
395+
PyErr_Restore(exc, val, tb);
396+
goto done;
397+
}
398+
399+
result = _add_pending_call(interp, func, arg);
390400
/* signal main loop */
391401
SIGNAL_PENDING_CALLS(interp);
392402

403+
done:
393404
if (lock != NULL)
394405
PyThread_release_lock(lock);
395406
return result;

Python/pylifecycle.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,8 +1459,19 @@ Py_EndInterpreter(PyThreadState *tstate)
14591459
if (tstate->frame != NULL)
14601460
Py_FatalError("Py_EndInterpreter: thread still has a frame");
14611461

1462+
// Mark as finalizing.
1463+
if (interp->ceval.pending.lock != NULL) {
1464+
PyThread_acquire_lock(interp->ceval.pending.lock, 1);
1465+
}
1466+
interp->finalizing = 1;
1467+
if (interp->ceval.pending.lock != NULL) {
1468+
PyThread_release_lock(interp->ceval.pending.lock);
1469+
}
1470+
1471+
// Wrap up existing threads.
14621472
wait_for_thread_shutdown();
14631473

1474+
// Make any pending calls.
14641475
if (_Py_atomic_load_relaxed(
14651476
&(interp->ceval.pending.calls_to_do)))
14661477
{

0 commit comments

Comments
 (0)