diff options
author | Tim Peters <tim.peters@gmail.com> | 2000-09-17 14:40:17 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2000-09-17 14:40:17 (GMT) |
commit | 6b184918f6611654d8501ecd467209ddcb33f027 (patch) | |
tree | 28b61af0e387cb6e72a5742a7a64d65c8e3fc871 /Objects/classobject.c | |
parent | df9e6b8196dc171fb764657c87fdf7378a1f47bd (diff) | |
download | cpython-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.c | 40 |
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); |