summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-01-21 00:42:25 (GMT)
committerGitHub <noreply@github.com>2022-01-21 00:42:25 (GMT)
commite9e3eab0b868c7d0b48e472705024240d5c39d5c (patch)
tree65c254d948a37dd822085887ebb84f390ad48d94 /Objects
parent27df7566bc19699b967e0e30d7808637b90141f6 (diff)
downloadcpython-e9e3eab0b868c7d0b48e472705024240d5c39d5c.zip
cpython-e9e3eab0b868c7d0b48e472705024240d5c39d5c.tar.gz
cpython-e9e3eab0b868c7d0b48e472705024240d5c39d5c.tar.bz2
bpo-46417: Finalize structseq types at exit (GH-30645)
Add _PyStructSequence_FiniType() and _PyStaticType_Dealloc() functions to finalize a structseq static type in Py_Finalize(). Currrently, these functions do nothing if Python is built in release mode. Clear static types: * AsyncGenHooksType: sys.set_asyncgen_hooks() * FlagsType: sys.flags * FloatInfoType: sys.float_info * Hash_InfoType: sys.hash_info * Int_InfoType: sys.int_info * ThreadInfoType: sys.thread_info * UnraisableHookArgsType: sys.unraisablehook * VersionInfoType: sys.version * WindowsVersionType: sys.getwindowsversion()
Diffstat (limited to 'Objects')
-rw-r--r--Objects/floatobject.c8
-rw-r--r--Objects/longobject.c11
-rw-r--r--Objects/structseq.c30
-rw-r--r--Objects/typeobject.c23
4 files changed, 70 insertions, 2 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index f8620d6..88f25d6 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -2082,6 +2082,14 @@ _PyFloat_Fini(PyInterpreterState *interp)
#endif
}
+void
+_PyFloat_FiniType(PyInterpreterState *interp)
+{
+ if (_Py_IsMainInterpreter(interp)) {
+ _PyStructSequence_FiniType(&FloatInfoType);
+ }
+}
+
/* Print summary info about the state of the optimized allocator */
void
_PyFloat_DebugMallocStats(FILE *out)
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 1b2d126..5aa53dd 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -5949,3 +5949,14 @@ _PyLong_InitTypes(PyInterpreterState *interp)
return _PyStatus_OK();
}
+
+
+void
+_PyLong_FiniTypes(PyInterpreterState *interp)
+{
+ if (!_Py_IsMainInterpreter(interp)) {
+ return;
+ }
+
+ _PyStructSequence_FiniType(&Int_InfoType);
+}
diff --git a/Objects/structseq.c b/Objects/structseq.c
index a2eefb0..f8bf947 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -532,6 +532,36 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
(void)PyStructSequence_InitType2(type, desc);
}
+
+void
+_PyStructSequence_FiniType(PyTypeObject *type)
+{
+ // Ensure that the type is initialized
+ assert(type->tp_name != NULL);
+ assert(type->tp_base == &PyTuple_Type);
+
+ // Cannot delete a type if it still has subclasses
+ if (type->tp_subclasses != NULL) {
+ return;
+ }
+
+ // Undo PyStructSequence_NewType()
+ type->tp_name = NULL;
+ PyMem_Free(type->tp_members);
+
+ _PyStaticType_Dealloc(type);
+ assert(Py_REFCNT(type) == 1);
+ // Undo Py_INCREF(type) of _PyStructSequence_InitType().
+ // Don't use Py_DECREF(): static type must not be deallocated
+ Py_SET_REFCNT(type, 0);
+
+ // Make sure that _PyStructSequence_InitType() will initialize
+ // the type again
+ assert(Py_REFCNT(type) == 0);
+ assert(type->tp_name == NULL);
+}
+
+
PyTypeObject *
PyStructSequence_NewType(PyStructSequence_Desc *desc)
{
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index cbf806b..66a10a5 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4070,10 +4070,27 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
extern void
_PyDictKeys_DecRef(PyDictKeysObject *keys);
+
+void
+_PyStaticType_Dealloc(PyTypeObject *type)
+{
+ // _PyStaticType_Dealloc() must not be called if a type has subtypes.
+ // A subtype can inherit attributes and methods of its parent type,
+ // and a type must no longer be used once it's deallocated.
+ assert(type->tp_subclasses == NULL);
+
+ Py_CLEAR(type->tp_dict);
+ Py_CLEAR(type->tp_bases);
+ Py_CLEAR(type->tp_mro);
+ Py_CLEAR(type->tp_cache);
+ Py_CLEAR(type->tp_subclasses);
+ type->tp_flags &= ~Py_TPFLAGS_READY;
+}
+
+
static void
type_dealloc(PyTypeObject *type)
{
- PyHeapTypeObject *et;
PyObject *tp, *val, *tb;
/* Assert this is a heap-allocated type object */
@@ -4082,8 +4099,8 @@ type_dealloc(PyTypeObject *type)
PyErr_Fetch(&tp, &val, &tb);
remove_all_subclasses(type, type->tp_bases);
PyErr_Restore(tp, val, tb);
+
PyObject_ClearWeakRefs((PyObject *)type);
- et = (PyHeapTypeObject *)type;
Py_XDECREF(type->tp_base);
Py_XDECREF(type->tp_dict);
Py_XDECREF(type->tp_bases);
@@ -4094,6 +4111,8 @@ type_dealloc(PyTypeObject *type)
* of most other objects. It's okay to cast it to char *.
*/
PyObject_Free((char *)type->tp_doc);
+
+ PyHeapTypeObject *et = (PyHeapTypeObject *)type;
Py_XDECREF(et->ht_name);
Py_XDECREF(et->ht_qualname);
Py_XDECREF(et->ht_slots);