mirror of
https://github.com/python/cpython.git
synced 2025-11-25 04:34:37 +00:00
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()
This commit is contained in:
parent
27df7566bc
commit
e9e3eab0b8
17 changed files with 230 additions and 2 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue