mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
PyType_Ready(): Complain if the type is a base type, and gc'able, and
tp_free is NULL or PyObject_Del at the end. Because it's a base type it must call tp_free in its dealloc function, and because it's gc'able it must not call PyObject_Del. inherit_slots(): Don't inherit tp_free unless the type and its base agree about whether they're gc'able. If the type is gc'able and the base is not, and the base uses the default PyObject_Del for its tp_free, give the type PyObject_GC_Del for its tp_free (the appropriate default for a gc'able type). cPickle.c: The Pickler and Unpickler types claim to be base classes and gc'able, but their dealloc functions didn't call tp_free. Repaired that. Also call PyType_Ready() on these typeobjects, so that the correct (PyObject_GC_Del) default memory-freeing function gets plugged into these types' tp_free slots.
This commit is contained in:
parent
4d508adae3
commit
3cfe75470d
3 changed files with 49 additions and 3 deletions
|
@ -3044,8 +3044,25 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
|
|||
COPYSLOT(tp_dictoffset);
|
||||
COPYSLOT(tp_init);
|
||||
COPYSLOT(tp_alloc);
|
||||
COPYSLOT(tp_free);
|
||||
COPYSLOT(tp_is_gc);
|
||||
if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) ==
|
||||
(base->tp_flags & Py_TPFLAGS_HAVE_GC)) {
|
||||
/* They agree about gc. */
|
||||
COPYSLOT(tp_free);
|
||||
}
|
||||
else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) &&
|
||||
type->tp_free == NULL &&
|
||||
base->tp_free == _PyObject_Del) {
|
||||
/* A bit of magic to plug in the correct default
|
||||
* tp_free function when a derived class adds gc,
|
||||
* didn't define tp_free, and the base uses the
|
||||
* default non-gc tp_free.
|
||||
*/
|
||||
type->tp_free = PyObject_GC_Del;
|
||||
}
|
||||
/* else they didn't agree about gc, and there isn't something
|
||||
* obvious to be done -- the type is on its own.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3149,6 +3166,19 @@ PyType_Ready(PyTypeObject *type)
|
|||
inherit_slots(type, (PyTypeObject *)b);
|
||||
}
|
||||
|
||||
/* Sanity check for tp_free. */
|
||||
if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&
|
||||
(type->tp_free == NULL || type->tp_free == PyObject_Del)) {
|
||||
/* This base class needs to call tp_free, but doesn't have
|
||||
* one, or its tp_free is for non-gc'ed objects.
|
||||
*/
|
||||
PyErr_Format(PyExc_TypeError, "type '%.100s' participates in "
|
||||
"gc and is a base type but has inappropriate "
|
||||
"tp_free slot",
|
||||
type->tp_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* if the type dictionary doesn't contain a __doc__, set it from
|
||||
the tp_doc slot.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue