bpo-36710: Add runtime variable to Py_FinalizeEx() by vstinner · Pull Request #12937 · python/cpython
int _Py_UnhandledKeyboardInterrupt = 0; _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
if (!_PyRuntime.initialized) _PyRuntimeState *runtime = &_PyRuntime; if (!runtime->initialized) { return status; }
// Wrap up existing "threading"-module-created, non-daemon threads. wait_for_thread_shutdown();
/* Get current thread state and interpreter pointer */ tstate = _PyThreadState_GET(); interp = tstate->interp;
// 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
/* Remaining threads (e.g. daemon threads) will automatically exit after taking the GIL (in PyEval_RestoreThread()). */ _PyRuntime.finalizing = tstate; _PyRuntime.initialized = 0; _PyRuntime.core_initialized = 0; runtime->finalizing = tstate; runtime->initialized = 0; runtime->core_initialized = 0;
/* Flush sys.stdout and sys.stderr */ if (flush_std_files() < 0) {
/* Cleanup auto-thread-state */ _PyGILState_Fini(); _PyGILState_Fini(runtime);
/* Delete current thread. After this, many C API calls become crashy. */ PyThreadState_Swap(NULL);
call_ll_exitfuncs(); call_ll_exitfuncs(runtime);
_PyRuntime_Finalize(); return status;
static void call_ll_exitfuncs(void) call_ll_exitfuncs(_PyRuntimeState *runtime) { while (_PyRuntime.nexitfuncs > 0) (*_PyRuntime.exitfuncs[--_PyRuntime.nexitfuncs])(); while (runtime->nexitfuncs > 0) { (*runtime->exitfuncs[--runtime->nexitfuncs])(); }
fflush(stdout); fflush(stderr);