diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-05-16-19-58.bpo-36479.FPztBY.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-05-16-19-58.bpo-36479.FPztBY.rst new file mode 100644 index 00000000000000..56f77de9c7e6e3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-05-16-19-58.bpo-36479.FPztBY.rst @@ -0,0 +1 @@ +Exit threads when interpreter is finalizing rather than runtime. \ No newline at end of file diff --git a/Python/ceval.c b/Python/ceval.c index e616a3f539898d..cc19b61d1be66b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -207,8 +207,11 @@ _PyEval_FiniThreads(void) static inline void exit_thread_if_finalizing(PyThreadState *tstate) { + /* Get interpreter pointer */ + PyInterpreterState *interp = tstate->interp; + /* _Py_Finalizing is protected by the GIL */ - if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) { + if (interp->finalizing && !_Py_CURRENTLY_FINALIZING(tstate)) { drop_gil(tstate); PyThread_exit_thread(); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index bd4d1d92662a69..989e0ec0fffd98 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1131,16 +1131,18 @@ Py_FinalizeEx(void) return status; } + /* Get current thread state and interpreter pointer */ + PyThreadState *tstate = _PyThreadState_GET(); + PyInterpreterState *interp = tstate->interp; + // Wrap up existing "threading"-module-created, non-daemon threads. wait_for_thread_shutdown(); + interp->finalizing = 1; + // Make any remaining pending calls. _Py_FinishPendingCalls(); - /* Get current thread state and interpreter pointer */ - PyThreadState *tstate = _PyThreadState_GET(); - PyInterpreterState *interp = tstate->interp; - /* The interpreter is still entirely intact at this point, and the * exit funcs may be relying on that. In particular, if some thread * or exit func is still waiting to do an import, the import machinery @@ -1546,10 +1548,10 @@ Py_EndInterpreter(PyThreadState *tstate) Py_FatalError("Py_EndInterpreter: thread is not current"); if (tstate->frame != NULL) Py_FatalError("Py_EndInterpreter: thread still has a frame"); - interp->finalizing = 1; // Wrap up existing "threading"-module-created, non-daemon threads. wait_for_thread_shutdown(); + interp->finalizing = 1; call_py_exitfuncs(interp);