From 1626bf4ac7aef1244e6f886e63a31f7ed65fbd10 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 22 Jan 2022 22:55:39 +0100 Subject: bpo-46417: Clear Unicode static types at exit (GH-30806) Add _PyUnicode_FiniTypes() function, called by finalize_interp_types(). It clears these static types: * EncodingMapType * PyFieldNameIter_Type * PyFormatterIter_Type _PyStaticType_Dealloc() now does nothing if tp_subclasses is not NULL. --- Include/internal/pycore_unicodeobject.h | 1 + Objects/exceptions.c | 6 ------ Objects/object.c | 4 ---- Objects/typeobject.c | 6 ++++-- Objects/unicodeobject.c | 29 +++++++++++++++++++---------- Python/pylifecycle.c | 1 + 6 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index 3b6dfe9..fabe522 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -17,6 +17,7 @@ extern void _PyUnicode_InitState(PyInterpreterState *); extern PyStatus _PyUnicode_InitGlobalObjects(PyInterpreterState *); extern PyStatus _PyUnicode_InitTypes(PyInterpreterState *); extern void _PyUnicode_Fini(PyInterpreterState *); +extern void _PyUnicode_FiniTypes(PyInterpreterState *); /* other API */ diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 6bf70e2..065503f 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -3545,12 +3545,6 @@ _PyExc_FiniTypes(PyInterpreterState *interp) for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) { PyTypeObject *exc = static_exceptions[i].exc; - - // Cannot delete a type if it still has subclasses - if (exc->tp_subclasses != NULL) { - continue; - } - _PyStaticType_Dealloc(exc); } } diff --git a/Objects/object.c b/Objects/object.c index 27f89e8..3082e70 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1994,10 +1994,6 @@ _PyTypes_FiniTypes(PyInterpreterState *interp) // their base classes. for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) { PyTypeObject *type = static_types[i]; - // Cannot delete a type if it still has subclasses - if (type->tp_subclasses != NULL) { - continue; - } _PyStaticType_Dealloc(type); } } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index bf62b53..cc4612f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4079,10 +4079,12 @@ type_dealloc_common(PyTypeObject *type) void _PyStaticType_Dealloc(PyTypeObject *type) { - // _PyStaticType_Dealloc() must not be called if a type has subtypes. + // If a type still has subtypes, it cannot be deallocated. // 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); + if (type->tp_subclasses != NULL) { + return; + } type_dealloc_common(type); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 2e1f8a6..4cea0d8 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -15567,23 +15567,19 @@ _PyUnicode_InitTypes(PyInterpreterState *interp) return _PyStatus_OK(); } - if (PyType_Ready(&PyUnicode_Type) < 0) { - return _PyStatus_ERR("Can't initialize unicode type"); - } - if (PyType_Ready(&PyUnicodeIter_Type) < 0) { - return _PyStatus_ERR("Can't initialize unicode iterator type"); - } - if (PyType_Ready(&EncodingMapType) < 0) { - return _PyStatus_ERR("Can't initialize encoding map type"); + goto error; } if (PyType_Ready(&PyFieldNameIter_Type) < 0) { - return _PyStatus_ERR("Can't initialize field name iterator type"); + goto error; } if (PyType_Ready(&PyFormatterIter_Type) < 0) { - return _PyStatus_ERR("Can't initialize formatter iter type"); + goto error; } return _PyStatus_OK(); + +error: + return _PyStatus_ERR("Can't initialize unicode types"); } @@ -16112,6 +16108,19 @@ 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); +} + + +void _PyUnicode_Fini(PyInterpreterState *interp) { struct _Py_unicode_state *state = &interp->unicode; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index aca3b1a..7fc9d3c 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1664,6 +1664,7 @@ flush_std_files(void) static void finalize_interp_types(PyInterpreterState *interp) { + _PyUnicode_FiniTypes(interp); _PySys_Fini(interp); _PyExc_Fini(interp); _PyFrame_Fini(interp); -- cgit v0.12