mirror of
https://github.com/python/cpython.git
synced 2025-10-22 06:32:43 +00:00
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()
This commit is contained in:
parent
70bf713617
commit
8e91c246e4
4 changed files with 29 additions and 24 deletions
|
@ -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);
|
||||||
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);
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
#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))
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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().
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue