summaryrefslogtreecommitdiffstats
path: root/Objects/classobject.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2000-09-17 14:40:17 (GMT)
committerTim Peters <tim.peters@gmail.com>2000-09-17 14:40:17 (GMT)
commit6b184918f6611654d8501ecd467209ddcb33f027 (patch)
tree28b61af0e387cb6e72a5742a7a64d65c8e3fc871 /Objects/classobject.c
parentdf9e6b8196dc171fb764657c87fdf7378a1f47bd (diff)
downloadcpython-6b184918f6611654d8501ecd467209ddcb33f027.zip
cpython-6b184918f6611654d8501ecd467209ddcb33f027.tar.gz
cpython-6b184918f6611654d8501ecd467209ddcb33f027.tar.bz2
Fix for SF bug 110688: Instance deallocation neglected to account for
that Py_INCREF boosts global _Py_RefTotal when Py_REF_DEBUG is defined but Py_TRACE_REFS isn't. There are, IMO, way too many preprocessor gimmicks in use for refcount debugging (at least 3 distinct true/false symbols, but not all 8 combos are supported by the code, etc etc), and no coherent documentation of this stuff -- 'twas too painful to track this one down.
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r--Objects/classobject.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c
index d963fe1..19059fc 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -487,37 +487,52 @@ instance_dealloc(register PyInstanceObject *inst)
PyObject *error_type, *error_value, *error_traceback;
PyObject *del;
static PyObject *delstr;
-#ifdef Py_TRACE_REFS
+#ifdef Py_REF_DEBUG
extern long _Py_RefTotal;
#endif
- /* Call the __del__ method if it exists. First temporarily
- revive the object and save the current exception, if any. */
+ /* Temporarily resurrect the object. */
#ifdef Py_TRACE_REFS
+#ifndef Py_REF_DEBUG
+# error "Py_TRACE_REFS defined but Py_REF_DEBUG not."
+#endif
/* much too complicated if Py_TRACE_REFS defined */
inst->ob_type = &PyInstance_Type;
_Py_NewReference((PyObject *)inst);
- _Py_RefTotal--; /* compensate for increment in NEWREF */
#ifdef COUNT_ALLOCS
- inst->ob_type->tp_alloc--; /* ditto */
+ /* compensate for boost in _Py_NewReference; note that
+ * _Py_RefTotal was also boosted; we'll knock that down later.
+ */
+ inst->ob_type->tp_alloc--;
#endif
#else /* !Py_TRACE_REFS */
+ /* Py_INCREF boosts _Py_RefTotal if Py_REF_DEBUG is defined */
Py_INCREF(inst);
#endif /* !Py_TRACE_REFS */
+
+ /* Save the current exception, if any. */
PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ /* Execute __del__ method, if any. */
if (delstr == NULL)
delstr = PyString_InternFromString("__del__");
if ((del = instance_getattr2(inst, delstr)) != NULL) {
PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);
- if (res == NULL) {
+ if (res == NULL)
PyErr_WriteUnraisable(del);
- }
else
Py_DECREF(res);
Py_DECREF(del);
}
- /* Restore the saved exception and undo the temporary revival */
+ /* Restore the saved exception. */
PyErr_Restore(error_type, error_value, error_traceback);
- /* Can't use DECREF here, it would cause a recursive call */
+ /* Undo the temporary resurrection; can't use DECREF here, it would
+ * cause a recursive call.
+ */
+#ifdef Py_REF_DEBUG
+ /* _Py_RefTotal was boosted either by _Py_NewReference or
+ * Py_INCREF above.
+ */
+ _Py_RefTotal--;
+#endif
if (--inst->ob_refcnt > 0) {
#ifdef COUNT_ALLOCS
inst->ob_type->tp_free--;
@@ -525,14 +540,15 @@ instance_dealloc(register PyInstanceObject *inst)
return; /* __del__ added a reference; don't delete now */
}
#ifdef Py_TRACE_REFS
+ _Py_ForgetReference((PyObject *)inst);
#ifdef COUNT_ALLOCS
- inst->ob_type->tp_free--; /* compensate for increment in UNREF */
+ /* compensate for increment in _Py_ForgetReference */
+ inst->ob_type->tp_free--;
#endif
- _Py_ForgetReference((PyObject *)inst);
#ifndef WITH_CYCLE_GC
inst->ob_type = NULL;
#endif
-#endif /* Py_TRACE_REFS */
+#endif
PyObject_GC_Fini(inst);
Py_DECREF(inst->in_class);
Py_XDECREF(inst->in_dict);