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.
This commit is contained in:
Victor Stinner 2019-11-20 10:38:34 +01:00 committed by GitHub
parent b8462477bf
commit 7eee5beaf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 58 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;
}