[Python-checkins] gh-94673: Properly Initialize and Finalize Static Builtin Types for Each Interpreter (gh-104072)

ericsnowcurrently webhook-mailer at python.org
Mon May 1 21:36:12 EDT 2023


https://github.com/python/cpython/commit/fdd878650d325297cd801305bc2d1b0e903e42b4
commit: fdd878650d325297cd801305bc2d1b0e903e42b4
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2023-05-01T19:36:00-06:00
summary:

gh-94673: Properly Initialize and Finalize Static Builtin Types for Each Interpreter (gh-104072)

Until now, we haven't been initializing nor finalizing the per-interpreter state properly.

files:
M Include/internal/pycore_object.h
M Include/internal/pycore_pylifecycle.h
M Include/internal/pycore_structseq.h
M Include/internal/pycore_typeobject.h
M Modules/_io/_iomodule.c
M Objects/exceptions.c
M Objects/floatobject.c
M Objects/longobject.c
M Objects/object.c
M Objects/structseq.c
M Objects/typeobject.c
M Objects/unicodeobject.c
M Objects/weakrefobject.c
M Python/errors.c
M Python/pylifecycle.c
M Python/sysmodule.c
M Python/thread.c

diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 2ca047846e09..2ee0180c0554 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -272,8 +272,9 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
 {
     if (PyType_Check(op) &&
             ((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
+        PyInterpreterState *interp = _PyInterpreterState_GET();
         static_builtin_state *state = _PyStaticType_GetState(
-                                                        (PyTypeObject *)op);
+                                                interp, (PyTypeObject *)op);
         return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
     }
     // Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index f96261a650da..7f8cc643ec0c 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -39,7 +39,7 @@ extern PyStatus _PySys_Create(
 extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
 extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
 extern int _PySys_UpdateConfig(PyThreadState *tstate);
-extern void _PySys_Fini(PyInterpreterState *interp);
+extern void _PySys_FiniTypes(PyInterpreterState *interp);
 extern int _PyBuiltins_AddExceptions(PyObject * bltinmod);
 extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
 
diff --git a/Include/internal/pycore_structseq.h b/Include/internal/pycore_structseq.h
index bd1e85c6883f..6f5dfc12707c 100644
--- a/Include/internal/pycore_structseq.h
+++ b/Include/internal/pycore_structseq.h
@@ -16,18 +16,22 @@ PyAPI_FUNC(PyTypeObject *) _PyStructSequence_NewType(
     unsigned long tp_flags);
 
 extern int _PyStructSequence_InitBuiltinWithFlags(
+    PyInterpreterState *interp,
     PyTypeObject *type,
     PyStructSequence_Desc *desc,
     unsigned long tp_flags);
 
 static inline int
-_PyStructSequence_InitBuiltin(PyTypeObject *type,
+_PyStructSequence_InitBuiltin(PyInterpreterState *interp,
+                              PyTypeObject *type,
                               PyStructSequence_Desc *desc)
 {
-    return _PyStructSequence_InitBuiltinWithFlags(type, desc, 0);
+    return _PyStructSequence_InitBuiltinWithFlags(interp, type, desc, 0);
 }
 
-extern void _PyStructSequence_FiniBuiltin(PyTypeObject *type);
+extern void _PyStructSequence_FiniBuiltin(
+    PyInterpreterState *interp,
+    PyTypeObject *type);
 
 #ifdef __cplusplus
 }
diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h
index 76253fd5fd86..5bd04736c01d 100644
--- a/Include/internal/pycore_typeobject.h
+++ b/Include/internal/pycore_typeobject.h
@@ -104,10 +104,10 @@ _PyType_GetModuleState(PyTypeObject *type)
 }
 
 
-extern int _PyStaticType_InitBuiltin(PyTypeObject *type);
-extern static_builtin_state * _PyStaticType_GetState(PyTypeObject *);
-extern void _PyStaticType_ClearWeakRefs(PyTypeObject *type);
-extern void _PyStaticType_Dealloc(PyTypeObject *type);
+extern int _PyStaticType_InitBuiltin(PyInterpreterState *, PyTypeObject *type);
+extern static_builtin_state * _PyStaticType_GetState(PyInterpreterState *, PyTypeObject *);
+extern void _PyStaticType_ClearWeakRefs(PyInterpreterState *, PyTypeObject *type);
+extern void _PyStaticType_Dealloc(PyInterpreterState *, PyTypeObject *);
 
 PyObject *
 _Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute);
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index a3bfbc9ac5a1..8ec3a6081c98 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -680,7 +680,7 @@ _PyIO_InitTypes(PyInterpreterState *interp)
 
     for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
         PyTypeObject *type = static_types[i];
-        if (_PyStaticType_InitBuiltin(type) < 0) {
+        if (_PyStaticType_InitBuiltin(interp, type) < 0) {
             return _PyStatus_ERR("Can't initialize builtin type");
         }
     }
@@ -691,15 +691,11 @@ _PyIO_InitTypes(PyInterpreterState *interp)
 void
 _PyIO_FiniTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
     // Deallocate types in the reverse order to deallocate subclasses before
     // their base classes.
     for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) {
         PyTypeObject *type = static_types[i];
-        _PyStaticType_Dealloc(type);
+        _PyStaticType_Dealloc(interp, type);
     }
 }
 
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 6c9dfbd9b415..ba5ee291f08b 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -3598,7 +3598,7 @@ _PyExc_InitTypes(PyInterpreterState *interp)
 {
     for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
         PyTypeObject *exc = static_exceptions[i].exc;
-        if (_PyStaticType_InitBuiltin(exc) < 0) {
+        if (_PyStaticType_InitBuiltin(interp, exc) < 0) {
             return -1;
         }
     }
@@ -3609,13 +3609,9 @@ _PyExc_InitTypes(PyInterpreterState *interp)
 static void
 _PyExc_FiniTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
     for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) {
         PyTypeObject *exc = static_exceptions[i].exc;
-        _PyStaticType_Dealloc(exc);
+        _PyStaticType_Dealloc(interp, exc);
     }
 }
 
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index a694ddcd019e..d257857d9c61 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1991,8 +1991,9 @@ PyStatus
 _PyFloat_InitTypes(PyInterpreterState *interp)
 {
     /* Init float info */
-    if (_PyStructSequence_InitBuiltin(&FloatInfoType,
-                                      &floatinfo_desc) < 0) {
+    if (_PyStructSequence_InitBuiltin(interp, &FloatInfoType,
+                                      &floatinfo_desc) < 0)
+    {
         return _PyStatus_ERR("can't init float info type");
     }
 
@@ -2028,9 +2029,7 @@ _PyFloat_Fini(PyInterpreterState *interp)
 void
 _PyFloat_FiniType(PyInterpreterState *interp)
 {
-    if (_Py_IsMainInterpreter(interp)) {
-        _PyStructSequence_FiniBuiltin(&FloatInfoType);
-    }
+    _PyStructSequence_FiniBuiltin(interp, &FloatInfoType);
 }
 
 /* Print summary info about the state of the optimized allocator */
diff --git a/Objects/longobject.c b/Objects/longobject.c
index de043488d7a1..853e934e2107 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -7,7 +7,6 @@
 #include "pycore_initconfig.h"    // _PyStatus_OK()
 #include "pycore_long.h"          // _Py_SmallInts
 #include "pycore_object.h"        // _PyObject_Init()
-#include "pycore_pystate.h"       // _Py_IsMainInterpreter()
 #include "pycore_runtime.h"       // _PY_NSMALLPOSINTS
 #include "pycore_structseq.h"     // _PyStructSequence_FiniBuiltin()
 
@@ -6352,7 +6351,9 @@ PyStatus
 _PyLong_InitTypes(PyInterpreterState *interp)
 {
     /* initialize int_info */
-    if (_PyStructSequence_InitBuiltin(&Int_InfoType, &int_info_desc) < 0) {
+    if (_PyStructSequence_InitBuiltin(interp, &Int_InfoType,
+                                      &int_info_desc) < 0)
+    {
         return _PyStatus_ERR("can't init int info type");
     }
 
@@ -6363,9 +6364,5 @@ _PyLong_InitTypes(PyInterpreterState *interp)
 void
 _PyLong_FiniTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
-    _PyStructSequence_FiniBuiltin(&Int_InfoType);
+    _PyStructSequence_FiniBuiltin(interp, &Int_InfoType);
 }
diff --git a/Objects/object.c b/Objects/object.c
index 4ce10cf1192d..ee8690101d3c 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -2105,7 +2105,7 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
     // All other static types (unless initialized elsewhere)
     for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
         PyTypeObject *type = static_types[i];
-        if (_PyStaticType_InitBuiltin(type) < 0) {
+        if (_PyStaticType_InitBuiltin(interp, type) < 0) {
             return _PyStatus_ERR("Can't initialize builtin type");
         }
         if (type == &PyType_Type) {
@@ -2128,15 +2128,11 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
 void
 _PyTypes_FiniTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
     // Deallocate types in the reverse order to deallocate subclasses before
     // their base classes.
     for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) {
         PyTypeObject *type = static_types[i];
-        _PyStaticType_Dealloc(type);
+        _PyStaticType_Dealloc(interp, type);
     }
 }
 
diff --git a/Objects/structseq.c b/Objects/structseq.c
index d8f55dc1eae5..ea476bf7a6a9 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -502,7 +502,8 @@ initialize_static_type(PyTypeObject *type, PyStructSequence_Desc *desc,
 }
 
 int
-_PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
+_PyStructSequence_InitBuiltinWithFlags(PyInterpreterState *interp,
+                                       PyTypeObject *type,
                                        PyStructSequence_Desc *desc,
                                        unsigned long tp_flags)
 {
@@ -536,7 +537,7 @@ _PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
     }
 #endif
 
-    if (_PyStaticType_InitBuiltin(type) < 0) {
+    if (_PyStaticType_InitBuiltin(interp, type) < 0) {
         PyErr_Format(PyExc_RuntimeError,
                      "Can't initialize builtin type %s",
                      desc->name);
@@ -606,7 +607,7 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
    initialized via _PyStructSequence_InitBuiltinWithFlags(). */
 
 void
-_PyStructSequence_FiniBuiltin(PyTypeObject *type)
+_PyStructSequence_FiniBuiltin(PyInterpreterState *interp, PyTypeObject *type)
 {
     // Ensure that the type is initialized
     assert(type->tp_name != NULL);
@@ -620,13 +621,15 @@ _PyStructSequence_FiniBuiltin(PyTypeObject *type)
         return;
     }
 
-    _PyStaticType_Dealloc(type);
+    _PyStaticType_Dealloc(interp, type);
 
-    // Undo _PyStructSequence_InitBuiltinWithFlags().
-    type->tp_name = NULL;
-    PyMem_Free(type->tp_members);
-    type->tp_members = NULL;
-    type->tp_base = NULL;
+    if (_Py_IsMainInterpreter(interp)) {
+        // Undo _PyStructSequence_InitBuiltinWithFlags().
+        type->tp_name = NULL;
+        PyMem_Free(type->tp_members);
+        type->tp_members = NULL;
+        type->tp_base = NULL;
+    }
 }
 
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 060d14e254ab..2ed806fb0155 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -69,13 +69,11 @@ static inline PyTypeObject * subclass_from_ref(PyObject *ref);
 
 /* helpers for for static builtin types */
 
-#ifndef NDEBUG
 static inline int
 static_builtin_index_is_set(PyTypeObject *self)
 {
     return self->tp_subclasses != NULL;
 }
-#endif
 
 static inline size_t
 static_builtin_index_get(PyTypeObject *self)
@@ -107,43 +105,46 @@ static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
 
 /* For static types we store some state in an array on each interpreter. */
 static_builtin_state *
-_PyStaticType_GetState(PyTypeObject *self)
+_PyStaticType_GetState(PyInterpreterState *interp, PyTypeObject *self)
 {
     assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
-    PyInterpreterState *interp = _PyInterpreterState_GET();
     return static_builtin_state_get(interp, self);
 }
 
+/* Set the type's per-interpreter state. */
 static void
-static_builtin_state_init(PyTypeObject *self)
+static_builtin_state_init(PyInterpreterState *interp, PyTypeObject *self)
 {
-    /* Set the type's per-interpreter state. */
-    PyInterpreterState *interp = _PyInterpreterState_GET();
+    if (!static_builtin_index_is_set(self)) {
+        static_builtin_index_set(self, interp->types.num_builtins_initialized);
+    }
+    static_builtin_state *state = static_builtin_state_get(interp, self);
 
     /* It should only be called once for each builtin type. */
-    assert(!static_builtin_index_is_set(self));
-
-    static_builtin_index_set(self, interp->types.num_builtins_initialized);
-    interp->types.num_builtins_initialized++;
-
-    static_builtin_state *state = static_builtin_state_get(interp, self);
+    assert(state->type == NULL);
     state->type = self;
+
     /* state->tp_subclasses is left NULL until init_subclasses() sets it. */
     /* state->tp_weaklist is left NULL until insert_head() or insert_after()
        (in weakrefobject.c) sets it. */
+
+    interp->types.num_builtins_initialized++;
 }
 
+/* Reset the type's per-interpreter state.
+   This basically undoes what static_builtin_state_init() did. */
 static void
-static_builtin_state_clear(PyTypeObject *self)
+static_builtin_state_clear(PyInterpreterState *interp, PyTypeObject *self)
 {
-    /* Reset the type's per-interpreter state.
-       This basically undoes what static_builtin_state_init() did. */
-    PyInterpreterState *interp = _PyInterpreterState_GET();
-
     static_builtin_state *state = static_builtin_state_get(interp, self);
+
+    assert(state->type != NULL);
     state->type = NULL;
     assert(state->tp_weaklist == NULL);  // It was already cleared out.
-    static_builtin_index_clear(self);
+
+    if (_Py_IsMainInterpreter(interp)) {
+        static_builtin_index_clear(self);
+    }
 
     assert(interp->types.num_builtins_initialized > 0);
     interp->types.num_builtins_initialized--;
@@ -4491,33 +4492,37 @@ clear_static_tp_subclasses(PyTypeObject *type)
     clear_subclasses(type);
 }
 
+static void
+clear_static_type_objects(PyInterpreterState *interp, PyTypeObject *type)
+{
+    if (_Py_IsMainInterpreter(interp)) {
+        Py_CLEAR(type->tp_dict);
+        Py_CLEAR(type->tp_bases);
+        Py_CLEAR(type->tp_mro);
+        Py_CLEAR(type->tp_cache);
+    }
+    clear_static_tp_subclasses(type);
+}
+
 void
-_PyStaticType_Dealloc(PyTypeObject *type)
+_PyStaticType_Dealloc(PyInterpreterState *interp, PyTypeObject *type)
 {
-    assert(!(type->tp_flags & Py_TPFLAGS_HEAPTYPE));
+    assert(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
+    assert(_Py_IsImmortal((PyObject *)type));
 
     type_dealloc_common(type);
 
-    Py_CLEAR(type->tp_dict);
-    Py_CLEAR(type->tp_bases);
-    Py_CLEAR(type->tp_mro);
-    Py_CLEAR(type->tp_cache);
-    clear_static_tp_subclasses(type);
+    clear_static_type_objects(interp, type);
 
-    // PyObject_ClearWeakRefs() raises an exception if Py_REFCNT() != 0
-    if (Py_REFCNT(type) == 0) {
-        PyObject_ClearWeakRefs((PyObject *)type);
+    if (_Py_IsMainInterpreter(interp)) {
+        type->tp_flags &= ~Py_TPFLAGS_READY;
+        type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+        type->tp_version_tag = 0;
     }
 
-    type->tp_flags &= ~Py_TPFLAGS_READY;
-    type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
-    type->tp_version_tag = 0;
-
-    if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
-        _PyStaticType_ClearWeakRefs(type);
-        static_builtin_state_clear(type);
-        /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
-    }
+    _PyStaticType_ClearWeakRefs(interp, type);
+    static_builtin_state_clear(interp, type);
+    /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
 }
 
 
@@ -4564,7 +4569,8 @@ static PyObject *
 lookup_subclasses(PyTypeObject *self)
 {
     if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
-        static_builtin_state *state = _PyStaticType_GetState(self);
+        PyInterpreterState *interp = _PyInterpreterState_GET();
+        static_builtin_state *state = _PyStaticType_GetState(interp, self);
         assert(state != NULL);
         return state->tp_subclasses;
     }
@@ -4574,8 +4580,9 @@ lookup_subclasses(PyTypeObject *self)
 int
 _PyType_HasSubclasses(PyTypeObject *self)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN &&
-            _PyStaticType_GetState(self) == NULL) {
+            _PyStaticType_GetState(interp, self) == NULL) {
         return 0;
     }
     if (lookup_subclasses(self) == NULL) {
@@ -6938,7 +6945,8 @@ type_ready_post_checks(PyTypeObject *type)
     else if (type->tp_dictoffset < (Py_ssize_t)sizeof(PyObject)) {
         if (type->tp_dictoffset + type->tp_basicsize <= 0) {
             PyErr_Format(PyExc_SystemError,
-                         "type %s has a tp_dictoffset that is too small");
+                         "type %s has a tp_dictoffset that is too small",
+                         type->tp_name);
         }
     }
     return 0;
@@ -7029,17 +7037,32 @@ PyType_Ready(PyTypeObject *type)
 }
 
 int
-_PyStaticType_InitBuiltin(PyTypeObject *self)
+_PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
 {
     assert(_Py_IsImmortal((PyObject *)self));
     assert(!(self->tp_flags & Py_TPFLAGS_HEAPTYPE));
+    assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_DICT));
+    assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF));
 
+#ifndef NDEBUG
+    int ismain = _Py_IsMainInterpreter(interp);
+#endif
     if (self->tp_flags & Py_TPFLAGS_READY) {
+        assert(!ismain);
         assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
+        assert(self->tp_flags & Py_TPFLAGS_VALID_VERSION_TAG);
+
+        static_builtin_state_init(interp, self);
+
+        /* Per-interpreter tp_subclasses is done lazily.
+           Otherwise we would initialize it here. */
+
         assert(_PyType_CheckConsistency(self));
         return 0;
     }
 
+    assert(ismain);
+
     self->tp_flags |= _Py_TPFLAGS_STATIC_BUILTIN;
     self->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
 
@@ -7047,11 +7070,11 @@ _PyStaticType_InitBuiltin(PyTypeObject *self)
     self->tp_version_tag = NEXT_GLOBAL_VERSION_TAG++;
     self->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
 
-    static_builtin_state_init(self);
+    static_builtin_state_init(interp, self);
 
     int res = type_ready(self);
     if (res < 0) {
-        static_builtin_state_clear(self);
+        static_builtin_state_clear(interp, self);
     }
     return res;
 }
@@ -7065,7 +7088,8 @@ init_subclasses(PyTypeObject *self)
         return NULL;
     }
     if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
-        static_builtin_state *state = _PyStaticType_GetState(self);
+        PyInterpreterState *interp = _PyInterpreterState_GET();
+        static_builtin_state *state = _PyStaticType_GetState(interp, self);
         state->tp_subclasses = subclasses;
         return subclasses;
     }
@@ -7080,7 +7104,8 @@ clear_subclasses(PyTypeObject *self)
        callers also test if tp_subclasses is NULL to check if a static type
        has no subclass. */
     if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
-        static_builtin_state *state = _PyStaticType_GetState(self);
+        PyInterpreterState *interp = _PyInterpreterState_GET();
+        static_builtin_state *state = _PyStaticType_GetState(interp, self);
         Py_CLEAR(state->tp_subclasses);
         return;
     }
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 7537c12e9268..6ae68cc20f7d 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -14573,13 +14573,13 @@ _PyUnicode_InitGlobalObjects(PyInterpreterState *interp)
 PyStatus
 _PyUnicode_InitTypes(PyInterpreterState *interp)
 {
-    if (_PyStaticType_InitBuiltin(&EncodingMapType) < 0) {
+    if (_PyStaticType_InitBuiltin(interp, &EncodingMapType) < 0) {
         goto error;
     }
-    if (_PyStaticType_InitBuiltin(&PyFieldNameIter_Type) < 0) {
+    if (_PyStaticType_InitBuiltin(interp, &PyFieldNameIter_Type) < 0) {
         goto error;
     }
-    if (_PyStaticType_InitBuiltin(&PyFormatterIter_Type) < 0) {
+    if (_PyStaticType_InitBuiltin(interp, &PyFormatterIter_Type) < 0) {
         goto error;
     }
     return _PyStatus_OK();
@@ -15158,13 +15158,9 @@ unicode_is_finalizing(void)
 void
 _PyUnicode_FiniTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
-    _PyStaticType_Dealloc(&EncodingMapType);
-    _PyStaticType_Dealloc(&PyFieldNameIter_Type);
-    _PyStaticType_Dealloc(&PyFormatterIter_Type);
+    _PyStaticType_Dealloc(interp, &EncodingMapType);
+    _PyStaticType_Dealloc(interp, &PyFieldNameIter_Type);
+    _PyStaticType_Dealloc(interp, &PyFormatterIter_Type);
 }
 
 
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index c1afe63ecf66..aee79fc1410b 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -1017,9 +1017,9 @@ PyObject_ClearWeakRefs(PyObject *object)
  * or anything else.
  */
 void
-_PyStaticType_ClearWeakRefs(PyTypeObject *type)
+_PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
 {
-    static_builtin_state *state = _PyStaticType_GetState(type);
+    static_builtin_state *state = _PyStaticType_GetState(interp, type);
     PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state);
     while (*list != NULL) {
         /* Note that clear_weakref() pops the first ref off the type's
diff --git a/Python/errors.c b/Python/errors.c
index ce72049b92de..a8000ac94918 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -1342,8 +1342,9 @@ static PyStructSequence_Desc UnraisableHookArgs_desc = {
 PyStatus
 _PyErr_InitTypes(PyInterpreterState *interp)
 {
-    if (_PyStructSequence_InitBuiltin(&UnraisableHookArgsType,
-                                      &UnraisableHookArgs_desc) < 0) {
+    if (_PyStructSequence_InitBuiltin(interp, &UnraisableHookArgsType,
+                                      &UnraisableHookArgs_desc) < 0)
+    {
         return _PyStatus_ERR("failed to initialize UnraisableHookArgs type");
     }
     return _PyStatus_OK();
@@ -1353,11 +1354,7 @@ _PyErr_InitTypes(PyInterpreterState *interp)
 void
 _PyErr_FiniTypes(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
-    _PyStructSequence_FiniBuiltin(&UnraisableHookArgsType);
+    _PyStructSequence_FiniBuiltin(interp, &UnraisableHookArgsType);
 }
 
 
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index ba248d208e42..b8a115236900 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1663,8 +1663,10 @@ flush_std_files(void)
 static void
 finalize_interp_types(PyInterpreterState *interp)
 {
+    _PyIO_FiniTypes(interp);
+
     _PyUnicode_FiniTypes(interp);
-    _PySys_Fini(interp);
+    _PySys_FiniTypes(interp);
     _PyExc_Fini(interp);
     _PyAsyncGen_Fini(interp);
     _PyContext_Fini(interp);
@@ -1706,8 +1708,6 @@ finalize_interp_clear(PyThreadState *tstate)
     /* Clear interpreter state and all thread states */
     _PyInterpreterState_Clear(tstate);
 
-    _PyIO_FiniTypes(tstate->interp);
-
     /* Clear all loghooks */
     /* Both _PySys_Audit function and users still need PyObject, such as tuple.
        Call _PySys_ClearAuditHooks when PyObject available. */
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 81dabe6102f1..781588b0df4e 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -3141,6 +3141,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
 {
     PyObject *version_info;
     int res;
+    PyInterpreterState *interp = tstate->interp;
 
     /* stdin/stdout/stderr are set in pylifecycle.c */
 
@@ -3166,7 +3167,9 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
     SET_SYS("float_info", PyFloat_GetInfo());
     SET_SYS("int_info", PyLong_GetInfo());
     /* initialize hash_info */
-    if (_PyStructSequence_InitBuiltin(&Hash_InfoType, &hash_info_desc) < 0) {
+    if (_PyStructSequence_InitBuiltin(interp, &Hash_InfoType,
+                                      &hash_info_desc) < 0)
+    {
         goto type_init_failed;
     }
     SET_SYS("hash_info", get_hash_info(tstate));
@@ -3190,7 +3193,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
 #define ENSURE_INFO_TYPE(TYPE, DESC) \
     do { \
         if (_PyStructSequence_InitBuiltinWithFlags( \
-                &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
+                interp, &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
             goto type_init_failed; \
         } \
     } while (0)
@@ -3226,8 +3229,9 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
     SET_SYS("thread_info", PyThread_GetInfo());
 
     /* initialize asyncgen_hooks */
-    if (_PyStructSequence_InitBuiltin(
-            &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) {
+    if (_PyStructSequence_InitBuiltin(interp, &AsyncGenHooksType,
+                                      &asyncgen_hooks_desc) < 0)
+    {
         goto type_init_failed;
     }
 
@@ -3489,20 +3493,20 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
 
 
 void
-_PySys_Fini(PyInterpreterState *interp)
+_PySys_FiniTypes(PyInterpreterState *interp)
 {
-    if (_Py_IsMainInterpreter(interp)) {
-        _PyStructSequence_FiniBuiltin(&VersionInfoType);
-        _PyStructSequence_FiniBuiltin(&FlagsType);
+    _PyStructSequence_FiniBuiltin(interp, &VersionInfoType);
+    _PyStructSequence_FiniBuiltin(interp, &FlagsType);
 #if defined(MS_WINDOWS)
-        _PyStructSequence_FiniBuiltin(&WindowsVersionType);
+    _PyStructSequence_FiniBuiltin(interp, &WindowsVersionType);
 #endif
-        _PyStructSequence_FiniBuiltin(&Hash_InfoType);
-        _PyStructSequence_FiniBuiltin(&AsyncGenHooksType);
+    _PyStructSequence_FiniBuiltin(interp, &Hash_InfoType);
+    _PyStructSequence_FiniBuiltin(interp, &AsyncGenHooksType);
 #ifdef __EMSCRIPTEN__
+    if (_Py_IsMainInterpreter(interp)) {
         Py_CLEAR(EmscriptenInfoType);
-#endif
     }
+#endif
 }
 
 
diff --git a/Python/thread.c b/Python/thread.c
index f90cd34a0735..7fc53f9b6136 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -137,7 +137,8 @@ PyThread_GetInfo(void)
     int len;
 #endif
 
-    if (_PyStructSequence_InitBuiltin(&ThreadInfoType, &threadinfo_desc) < 0) {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    if (_PyStructSequence_InitBuiltin(interp, &ThreadInfoType, &threadinfo_desc) < 0) {
         return NULL;
     }
 
@@ -191,9 +192,5 @@ PyThread_GetInfo(void)
 void
 _PyThread_FiniType(PyInterpreterState *interp)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
-    _PyStructSequence_FiniBuiltin(&ThreadInfoType);
+    _PyStructSequence_FiniBuiltin(interp, &ThreadInfoType);
 }



More information about the Python-checkins mailing list