From 8e91c246e468515b877690e090c73f496552541d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 17:24:01 +0200 Subject: [PATCH] bpo-36710: Add runtime variable to Py_FinalizeEx() (GH-12937) * Add a 'runtime' variable to Py_FinalizeEx() rather than working directly on the global variable _PyRuntime * Add a 'runtime' parameter to _PyGC_Fini(), _PyGILState_Fini() and call_ll_exitfuncs() --- Include/internal/pycore_pylifecycle.h | 6 +++-- Modules/gcmodule.c | 5 ++-- Python/pylifecycle.c | 35 ++++++++++++++------------- Python/pystate.c | 7 +++--- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index bfff24b80a9..f07bc427bb8 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_pystate.h" /* _PyRuntimeState */ + /* True if the main interpreter thread exited due to an unhandled * KeyboardInterrupt exception, suggesting the user pressed ^C. */ PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; @@ -63,7 +65,7 @@ extern void PyAsyncGen_Fini(void); extern void _PyExc_Fini(void); extern void _PyImport_Fini(void); extern void _PyImport_Fini2(void); -extern void _PyGC_Fini(void); +extern void _PyGC_Fini(_PyRuntimeState *runtime); extern void _PyType_Fini(void); extern void _Py_HashRandomization_Fini(void); extern void _PyUnicode_Fini(void); @@ -73,7 +75,7 @@ extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Fini(void); extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); -extern void _PyGILState_Fini(void); +extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index a75d5fed95f..f36c7f5d5e4 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1865,9 +1865,10 @@ _PyGC_DumpShutdownStats(void) } void -_PyGC_Fini(void) +_PyGC_Fini(_PyRuntimeState *runtime) { - Py_CLEAR(_PyRuntime.gc.callbacks); + struct _gc_runtime_state *gc = &runtime->gc; + Py_CLEAR(gc->callbacks); } /* for debugging */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index c7920ef6262..fe4cb97a474 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -65,7 +65,7 @@ static _PyInitError init_sys_streams(PyInterpreterState *interp); static _PyInitError initsigs(void); static void call_py_exitfuncs(PyInterpreterState *); static void wait_for_thread_shutdown(void); -static void call_ll_exitfuncs(void); +static void call_ll_exitfuncs(_PyRuntimeState *runtime); int _Py_UnhandledKeyboardInterrupt = 0; _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; @@ -1131,23 +1131,23 @@ flush_std_files(void) int Py_FinalizeEx(void) { - PyInterpreterState *interp; - PyThreadState *tstate; int status = 0; - 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 @@ -1174,9 +1174,9 @@ Py_FinalizeEx(void) /* 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) { @@ -1294,7 +1294,7 @@ Py_FinalizeEx(void) PyFloat_Fini(); PyDict_Fini(); PySlice_Fini(); - _PyGC_Fini(); + _PyGC_Fini(runtime); _Py_HashRandomization_Fini(); _PyArg_Fini(); PyAsyncGen_Fini(); @@ -1314,7 +1314,7 @@ Py_FinalizeEx(void) PyGrammar_RemoveAccelerators(&_PyParser_Grammar); /* Cleanup auto-thread-state */ - _PyGILState_Fini(); + _PyGILState_Fini(runtime); /* Delete current thread. After this, many C API calls become crashy. */ PyThreadState_Swap(NULL); @@ -1336,7 +1336,7 @@ Py_FinalizeEx(void) } #endif - call_ll_exitfuncs(); + call_ll_exitfuncs(runtime); _PyRuntime_Finalize(); return status; @@ -2223,10 +2223,11 @@ int Py_AtExit(void (*func)(void)) } 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); diff --git a/Python/pystate.c b/Python/pystate.c index 6aaf993cfe2..498a9546e1b 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1078,10 +1078,11 @@ _PyGILState_GetInterpreterStateUnsafe(void) } void -_PyGILState_Fini(void) +_PyGILState_Fini(_PyRuntimeState *runtime) { - PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); - _PyRuntime.gilstate.autoInterpreterState = NULL; + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + PyThread_tss_delete(&gilstate->autoTSSkey); + gilstate->autoInterpreterState = NULL; } /* Reset the TSS key - called by PyOS_AfterFork_Child().