]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38858: Factorize Py_EndInterpreter() code (GH-17273)
authorVictor Stinner <vstinner@python.org>
Wed, 20 Nov 2019 09:38:34 +0000 (10:38 +0100)
committerGitHub <noreply@github.com>
Wed, 20 Nov 2019 09:38:34 +0000 (10:38 +0100)
* 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
Modules/gcmodule.c
Python/pylifecycle.c
Python/pystate.c

index f269ffe786893b0af54d06653cb34d2e05eef8b0..b2f2ad841c8e053d514e61b0ac9c277aa996415e 100644 (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);
 
index 05ca026189b677dcaa406e737f98f0dece30749e..518b0547d2745fe8b09669315ae282bc546f2022 100644 (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);
 }
index edff7f8f5e2a2942bf3f958cc123ca9add66dbb8..2975b3ebd6651dd4565791f45f38dee21c985649 100644 (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 */
index 99f93bb77c7b803882351eac2f2a125536d88024..8fff161dac0f50dd7de136ab553ea9235138aa90 100644 (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;
 }