summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorEddie Elizondo <eduardo.elizondorueda@gmail.com>2019-09-11 09:17:13 (GMT)
committerPetr Viktorin <encukou@gmail.com>2019-09-11 09:17:13 (GMT)
commitff023ed36ea260ab64be5895f1f1f087c798987a (patch)
treedd5e417057ca8cc75876ddda2b292bcce727e249 /Objects
parent7264e92b718d307cc499b2f10eab7644b00f0499 (diff)
downloadcpython-ff023ed36ea260ab64be5895f1f1f087c798987a.zip
cpython-ff023ed36ea260ab64be5895f1f1f087c798987a.tar.gz
cpython-ff023ed36ea260ab64be5895f1f1f087c798987a.tar.bz2
bpo-37879: Suppress subtype_dealloc decref when base type is a C heap type (GH-15323)
The instance destructor for a type is responsible for preparing an instance for deallocation by decrementing the reference counts of its referents. If an instance belongs to a heap type, the type object of an instance has its reference count decremented while for static types, which are permanently allocated, the type object is unaffected by the instance destructor. Previously, the default instance destructor searched the class hierarchy for an inherited instance destructor and, if present, would invoke it. Then, if the instance type is a heap type, it would decrement the reference count of that heap type. However, this could result in the premature destruction of a type because the inherited instance destructor should have already decremented the reference count of the type object. This change avoids the premature destruction of the type object by suppressing the decrement of its reference count when an inherited, non-default instance destructor has been invoked. Finally, an assertion on the Py_SIZE of a type was deleted. Heap types have a non zero size, making this into an incorrect assertion. https://github.com/python/cpython/pull/15323
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 883bc22..7575e55 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1157,11 +1157,9 @@ subtype_dealloc(PyObject *self)
/* Test whether the type has GC exactly once */
if (!PyType_IS_GC(type)) {
- /* It's really rare to find a dynamic type that doesn't have
- GC; it can only happen when deriving from 'object' and not
- adding any slots or instance variables. This allows
- certain simplifications: there's no need to call
- clear_slots(), or DECREF the dict, or clear weakrefs. */
+ /* A non GC dynamic type allows certain simplifications:
+ there's no need to call clear_slots(), or DECREF the dict,
+ or clear weakrefs. */
/* Maybe call finalizer; exit early if resurrected */
if (type->tp_finalize) {
@@ -1177,7 +1175,6 @@ subtype_dealloc(PyObject *self)
/* Find the nearest base with a different tp_dealloc */
base = type;
while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
- assert(Py_SIZE(base) == 0);
base = base->tp_base;
assert(base);
}
@@ -1189,8 +1186,10 @@ subtype_dealloc(PyObject *self)
assert(basedealloc);
basedealloc(self);
- /* Can't reference self beyond this point */
- Py_DECREF(type);
+ /* Only decref if the base type is not already a heap allocated type.
+ Otherwise, basedealloc should have decref'd it already */
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE))
+ Py_DECREF(type);
/* Done */
return;
@@ -1289,8 +1288,9 @@ subtype_dealloc(PyObject *self)
/* Can't reference self beyond this point. It's possible tp_del switched
our type from a HEAPTYPE to a non-HEAPTYPE, so be careful about
- reference counting. */
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
+ reference counting. Only decref if the base type is not already a heap
+ allocated type. Otherwise, basedealloc should have decref'd it already */
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE))
Py_DECREF(type);
endlabel: