Commit 8e91c246 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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()
parent 70bf7136
...@@ -8,6 +8,8 @@ extern "C" { ...@@ -8,6 +8,8 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define" # error "this header requires Py_BUILD_CORE define"
#endif #endif
#include "pycore_pystate.h" /* _PyRuntimeState */
/* True if the main interpreter thread exited due to an unhandled /* True if the main interpreter thread exited due to an unhandled
* KeyboardInterrupt exception, suggesting the user pressed ^C. */ * KeyboardInterrupt exception, suggesting the user pressed ^C. */
PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt;
...@@ -63,7 +65,7 @@ extern void PyAsyncGen_Fini(void); ...@@ -63,7 +65,7 @@ extern void PyAsyncGen_Fini(void);
extern void _PyExc_Fini(void); extern void _PyExc_Fini(void);
extern void _PyImport_Fini(void); extern void _PyImport_Fini(void);
extern void _PyImport_Fini2(void); extern void _PyImport_Fini2(void);
extern void _PyGC_Fini(void); extern void _PyGC_Fini(_PyRuntimeState *runtime);
extern void _PyType_Fini(void); extern void _PyType_Fini(void);
extern void _Py_HashRandomization_Fini(void); extern void _Py_HashRandomization_Fini(void);
extern void _PyUnicode_Fini(void); extern void _PyUnicode_Fini(void);
...@@ -73,7 +75,7 @@ extern void _PyHash_Fini(void); ...@@ -73,7 +75,7 @@ extern void _PyHash_Fini(void);
extern int _PyTraceMalloc_Fini(void); extern int _PyTraceMalloc_Fini(void);
extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
extern void _PyGILState_Fini(void); extern void _PyGILState_Fini(_PyRuntimeState *runtime);
PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
......
...@@ -1865,9 +1865,10 @@ _PyGC_DumpShutdownStats(void) ...@@ -1865,9 +1865,10 @@ _PyGC_DumpShutdownStats(void)
} }
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 */ /* for debugging */
......
...@@ -65,7 +65,7 @@ static _PyInitError init_sys_streams(PyInterpreterState *interp); ...@@ -65,7 +65,7 @@ static _PyInitError init_sys_streams(PyInterpreterState *interp);
static _PyInitError initsigs(void); static _PyInitError initsigs(void);
static void call_py_exitfuncs(PyInterpreterState *); static void call_py_exitfuncs(PyInterpreterState *);
static void wait_for_thread_shutdown(void); static void wait_for_thread_shutdown(void);
static void call_ll_exitfuncs(void); static void call_ll_exitfuncs(_PyRuntimeState *runtime);
int _Py_UnhandledKeyboardInterrupt = 0; int _Py_UnhandledKeyboardInterrupt = 0;
_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
...@@ -1131,23 +1131,23 @@ flush_std_files(void) ...@@ -1131,23 +1131,23 @@ flush_std_files(void)
int int
Py_FinalizeEx(void) Py_FinalizeEx(void)
{ {
PyInterpreterState *interp;
PyThreadState *tstate;
int status = 0; int status = 0;
if (!_PyRuntime.initialized) _PyRuntimeState *runtime = &_PyRuntime;
if (!runtime->initialized) {
return status; return status;
}
// Wrap up existing "threading"-module-created, non-daemon threads. // Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(); wait_for_thread_shutdown();
/* Get current thread state and interpreter pointer */
tstate = _PyThreadState_GET();
interp = tstate->interp;
// Make any remaining pending calls. // Make any remaining pending calls.
_Py_FinishPendingCalls(); _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 /* The interpreter is still entirely intact at this point, and the
* exit funcs may be relying on that. In particular, if some thread * 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 * or exit func is still waiting to do an import, the import machinery
...@@ -1174,9 +1174,9 @@ Py_FinalizeEx(void) ...@@ -1174,9 +1174,9 @@ Py_FinalizeEx(void)
/* Remaining threads (e.g. daemon threads) will automatically exit /* Remaining threads (e.g. daemon threads) will automatically exit
after taking the GIL (in PyEval_RestoreThread()). */ after taking the GIL (in PyEval_RestoreThread()). */
_PyRuntime.finalizing = tstate; runtime->finalizing = tstate;
_PyRuntime.initialized = 0; runtime->initialized = 0;
_PyRuntime.core_initialized = 0; runtime->core_initialized = 0;
/* Flush sys.stdout and sys.stderr */ /* Flush sys.stdout and sys.stderr */
if (flush_std_files() < 0) { if (flush_std_files() < 0) {
...@@ -1294,7 +1294,7 @@ Py_FinalizeEx(void) ...@@ -1294,7 +1294,7 @@ Py_FinalizeEx(void)
PyFloat_Fini(); PyFloat_Fini();
PyDict_Fini(); PyDict_Fini();
PySlice_Fini(); PySlice_Fini();
_PyGC_Fini(); _PyGC_Fini(runtime);
_Py_HashRandomization_Fini(); _Py_HashRandomization_Fini();
_PyArg_Fini(); _PyArg_Fini();
PyAsyncGen_Fini(); PyAsyncGen_Fini();
...@@ -1314,7 +1314,7 @@ Py_FinalizeEx(void) ...@@ -1314,7 +1314,7 @@ Py_FinalizeEx(void)
PyGrammar_RemoveAccelerators(&_PyParser_Grammar); PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
/* Cleanup auto-thread-state */ /* Cleanup auto-thread-state */
_PyGILState_Fini(); _PyGILState_Fini(runtime);
/* Delete current thread. After this, many C API calls become crashy. */ /* Delete current thread. After this, many C API calls become crashy. */
PyThreadState_Swap(NULL); PyThreadState_Swap(NULL);
...@@ -1336,7 +1336,7 @@ Py_FinalizeEx(void) ...@@ -1336,7 +1336,7 @@ Py_FinalizeEx(void)
} }
#endif #endif
call_ll_exitfuncs(); call_ll_exitfuncs(runtime);
_PyRuntime_Finalize(); _PyRuntime_Finalize();
return status; return status;
...@@ -2223,10 +2223,11 @@ int Py_AtExit(void (*func)(void)) ...@@ -2223,10 +2223,11 @@ int Py_AtExit(void (*func)(void))
} }
static void static void
call_ll_exitfuncs(void) call_ll_exitfuncs(_PyRuntimeState *runtime)
{ {
while (_PyRuntime.nexitfuncs > 0) while (runtime->nexitfuncs > 0) {
(*_PyRuntime.exitfuncs[--_PyRuntime.nexitfuncs])(); (*runtime->exitfuncs[--runtime->nexitfuncs])();
}
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
......
...@@ -1078,10 +1078,11 @@ _PyGILState_GetInterpreterStateUnsafe(void) ...@@ -1078,10 +1078,11 @@ _PyGILState_GetInterpreterStateUnsafe(void)
} }
void void
_PyGILState_Fini(void) _PyGILState_Fini(_PyRuntimeState *runtime)
{ {
PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
_PyRuntime.gilstate.autoInterpreterState = NULL; PyThread_tss_delete(&gilstate->autoTSSkey);
gilstate->autoInterpreterState = NULL;
} }
/* Reset the TSS key - called by PyOS_AfterFork_Child(). /* Reset the TSS key - called by PyOS_AfterFork_Child().
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment