Skip to content

Commit

Permalink
bpo-38858: Factorize Py_EndInterpreter() code (pythonGH-17273)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
vstinner authored and Jake Taylor committed Dec 5, 2019
1 parent 6bbbe7e commit f897c98
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 58 deletions.
4 changes: 2 additions & 2 deletions Include/internal/pycore_pylifecycle.h
Expand Up @@ -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);
Expand All @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions Modules/gcmodule.c
Expand Up @@ -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);
}
Expand Down
128 changes: 76 additions & 52 deletions Python/pylifecycle.c
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions Python/pystate.c
Expand Up @@ -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;
}
Expand Down

0 comments on commit f897c98

Please sign in to comment.