diff options
author | Tim Peters <tim.peters@gmail.com> | 2003-05-21 21:29:48 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2003-05-21 21:29:48 (GMT) |
commit | 3cfe75470d1f77468be01002d09d884c3a431827 (patch) | |
tree | c788b7ba4ecea492c834d78a16e574a96049ae43 /Objects | |
parent | 4d508adae3101434ae62be1c140e9877673dc257 (diff) | |
download | cpython-3cfe75470d1f77468be01002d09d884c3a431827.zip cpython-3cfe75470d1f77468be01002d09d884c3a431827.tar.gz cpython-3cfe75470d1f77468be01002d09d884c3a431827.tar.bz2 |
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.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9a23227..18b50fc 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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. */ |