From 7eee5beaf87be898a679278c480e8dd0df76d351 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Nov 2019 10:38:34 +0100 Subject: bpo-38858: Factorize Py_EndInterpreter() code (GH-17273) * Factorize code in common between Py_FinalizeEx() and Py_EndInterpreter(). * Py_EndInterpreter() now also calls _PyWarnings_Fini(). * Call _PyExc_Fini() and _PyGC_Fini() later in the finalization. --- Include/internal/pycore_pylifecycle.h | 4 +- Modules/gcmodule.c | 4 +- Python/pylifecycle.c | 128 ++++++++++++++++++++-------------- Python/pystate.c | 4 +- 4 files changed, 82 insertions(+), 58 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index f269ffe..b2f2ad8 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -76,7 +76,7 @@ extern void PyOS_FiniInterrupts(void); extern void _PyExc_Fini(void); extern void _PyImport_Fini(void); extern void _PyImport_Fini2(void); -extern void _PyGC_Fini(struct pyruntimestate *runtime); +extern void _PyGC_Fini(PyThreadState *tstate); extern void _PyType_Fini(void); extern void _Py_HashRandomization_Fini(void); extern void _PyUnicode_Fini(void); @@ -87,7 +87,7 @@ extern void _PyTraceMalloc_Fini(void); extern void _PyWarnings_Fini(PyInterpreterState *interp); extern void _PyGILState_Init(PyThreadState *tstate); -extern void _PyGILState_Fini(struct pyruntimestate *runtime); +extern void _PyGILState_Fini(PyThreadState *tstate); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(struct pyruntimestate *runtime); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 05ca026..518b054 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -2038,9 +2038,9 @@ _PyGC_DumpShutdownStats(_PyRuntimeState *runtime) } void -_PyGC_Fini(_PyRuntimeState *runtime) +_PyGC_Fini(PyThreadState *tstate) { - struct _gc_runtime_state *state = &runtime->gc; + struct _gc_runtime_state *state = &tstate->interp->runtime->gc; Py_CLEAR(state->garbage); Py_CLEAR(state->callbacks); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index edff7f8..2975b3e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1161,6 +1161,78 @@ flush_std_files(void) */ + +static void +finalize_interp_types(PyThreadState *tstate, int is_main_interp) +{ + if (is_main_interp) { + /* Sundry finalizers */ + _PyMethod_Fini(); + _PyFrame_Fini(); + _PyCFunction_Fini(); + _PyTuple_Fini(); + _PyList_Fini(); + _PySet_Fini(); + _PyBytes_Fini(); + _PyLong_Fini(); + _PyFloat_Fini(); + _PyDict_Fini(); + _PySlice_Fini(); + } + + _PyWarnings_Fini(tstate->interp); + + if (is_main_interp) { + _Py_HashRandomization_Fini(); + _PyArg_Fini(); + _PyAsyncGen_Fini(); + _PyContext_Fini(); + + /* Cleanup Unicode implementation */ + _PyUnicode_Fini(); + _Py_ClearFileSystemEncoding(); + } +} + + +static void +finalize_interp_clear(PyThreadState *tstate, int is_main_interp) +{ + /* Clear interpreter state and all thread states */ + PyInterpreterState_Clear(tstate->interp); + + finalize_interp_types(tstate, is_main_interp); + + if (is_main_interp) { + /* XXX Still allocated: + - various static ad-hoc pointers to interned strings + - int and float free list blocks + - whatever various modules and libraries allocate + */ + + PyGrammar_RemoveAccelerators(&_PyParser_Grammar); + + _PyExc_Fini(); + _PyGC_Fini(tstate); + } +} + + +static void +finalize_interp_delete(PyThreadState *tstate, int is_main_interp) +{ + if (is_main_interp) { + /* Cleanup auto-thread-state */ + _PyGILState_Fini(tstate); + } + + /* Delete current thread. After this, many C API calls become crashy. */ + PyThreadState_Swap(NULL); + + PyInterpreterState_Delete(tstate->interp); +} + + int Py_FinalizeEx(void) { @@ -1314,56 +1386,9 @@ Py_FinalizeEx(void) } #endif /* Py_TRACE_REFS */ - /* Clear interpreter state and all thread states. */ - PyInterpreterState_Clear(interp); + finalize_interp_clear(tstate, 1); - /* Now we decref the exception classes. After this point nothing - can raise an exception. That's okay, because each Fini() method - below has been checked to make sure no exceptions are ever - raised. - */ - - _PyExc_Fini(); - - /* Sundry finalizers */ - _PyMethod_Fini(); - _PyFrame_Fini(); - _PyCFunction_Fini(); - _PyTuple_Fini(); - _PyList_Fini(); - _PySet_Fini(); - _PyBytes_Fini(); - _PyLong_Fini(); - _PyFloat_Fini(); - _PyDict_Fini(); - _PySlice_Fini(); - _PyGC_Fini(runtime); - _PyWarnings_Fini(interp); - _Py_HashRandomization_Fini(); - _PyArg_Fini(); - _PyAsyncGen_Fini(); - _PyContext_Fini(); - - /* Cleanup Unicode implementation */ - _PyUnicode_Fini(); - - _Py_ClearFileSystemEncoding(); - - /* XXX Still allocated: - - various static ad-hoc pointers to interned strings - - int and float free list blocks - - whatever various modules and libraries allocate - */ - - PyGrammar_RemoveAccelerators(&_PyParser_Grammar); - - /* Cleanup auto-thread-state */ - _PyGILState_Fini(runtime); - - /* Delete current thread. After this, many C API calls become crashy. */ - PyThreadState_Swap(NULL); - - PyInterpreterState_Delete(interp); + finalize_interp_delete(tstate, 1); #ifdef Py_TRACE_REFS /* Display addresses (& refcnts) of all objects still alive. @@ -1607,9 +1632,8 @@ Py_EndInterpreter(PyThreadState *tstate) } _PyImport_Cleanup(tstate); - PyInterpreterState_Clear(interp); - PyThreadState_Swap(NULL); - PyInterpreterState_Delete(interp); + finalize_interp_clear(tstate, 0); + finalize_interp_delete(tstate, 0); } /* Add the __main__ module */ diff --git a/Python/pystate.c b/Python/pystate.c index 99f93bb..8fff161 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1143,9 +1143,9 @@ _PyGILState_GetInterpreterStateUnsafe(void) } void -_PyGILState_Fini(_PyRuntimeState *runtime) +_PyGILState_Fini(PyThreadState *tstate) { - struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; PyThread_tss_delete(&gilstate->autoTSSkey); gilstate->autoInterpreterState = NULL; } -- cgit v0.12