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 _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(struct pyruntimestate *runtime); extern void _PyGC_Fini(PyThreadState *tstate);
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);
@ -87,7 +87,7 @@ extern void _PyTraceMalloc_Fini(void);
extern void _PyWarnings_Fini(PyInterpreterState *interp); extern void _PyWarnings_Fini(PyInterpreterState *interp);
extern void _PyGILState_Init(PyThreadState *tstate); 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); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(struct pyruntimestate *runtime);

View File

@ -2038,9 +2038,9 @@ _PyGC_DumpShutdownStats(_PyRuntimeState *runtime)
} }
void 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->garbage);
Py_CLEAR(state->callbacks); 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 int
Py_FinalizeEx(void) Py_FinalizeEx(void)
{ {
@ -1314,56 +1386,9 @@ Py_FinalizeEx(void)
} }
#endif /* Py_TRACE_REFS */ #endif /* Py_TRACE_REFS */
/* Clear interpreter state and all thread states. */ finalize_interp_clear(tstate, 1);
PyInterpreterState_Clear(interp);
/* Now we decref the exception classes. After this point nothing finalize_interp_delete(tstate, 1);
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);
#ifdef Py_TRACE_REFS #ifdef Py_TRACE_REFS
/* Display addresses (& refcnts) of all objects still alive. /* Display addresses (& refcnts) of all objects still alive.
@ -1607,9 +1632,8 @@ Py_EndInterpreter(PyThreadState *tstate)
} }
_PyImport_Cleanup(tstate); _PyImport_Cleanup(tstate);
PyInterpreterState_Clear(interp); finalize_interp_clear(tstate, 0);
PyThreadState_Swap(NULL); finalize_interp_delete(tstate, 0);
PyInterpreterState_Delete(interp);
} }
/* Add the __main__ module */ /* Add the __main__ module */

View File

@ -1143,9 +1143,9 @@ _PyGILState_GetInterpreterStateUnsafe(void)
} }
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); PyThread_tss_delete(&gilstate->autoTSSkey);
gilstate->autoInterpreterState = NULL; gilstate->autoInterpreterState = NULL;
} }