mirror of
https://github.com/python/cpython.git
synced 2025-12-04 08:34:25 +00:00
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.
This commit is contained in:
parent
df9e6b8196
commit
6b184918f6
1 changed files with 29 additions and 13 deletions
|
|
@ -487,37 +487,52 @@ instance_dealloc(register PyInstanceObject *inst)
|
||||||
PyObject *error_type, *error_value, *error_traceback;
|
PyObject *error_type, *error_value, *error_traceback;
|
||||||
PyObject *del;
|
PyObject *del;
|
||||||
static PyObject *delstr;
|
static PyObject *delstr;
|
||||||
#ifdef Py_TRACE_REFS
|
#ifdef Py_REF_DEBUG
|
||||||
extern long _Py_RefTotal;
|
extern long _Py_RefTotal;
|
||||||
#endif
|
#endif
|
||||||
/* Call the __del__ method if it exists. First temporarily
|
/* Temporarily resurrect the object. */
|
||||||
revive the object and save the current exception, if any. */
|
|
||||||
#ifdef Py_TRACE_REFS
|
#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 */
|
/* much too complicated if Py_TRACE_REFS defined */
|
||||||
inst->ob_type = &PyInstance_Type;
|
inst->ob_type = &PyInstance_Type;
|
||||||
_Py_NewReference((PyObject *)inst);
|
_Py_NewReference((PyObject *)inst);
|
||||||
_Py_RefTotal--; /* compensate for increment in NEWREF */
|
|
||||||
#ifdef COUNT_ALLOCS
|
#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
|
#endif
|
||||||
#else /* !Py_TRACE_REFS */
|
#else /* !Py_TRACE_REFS */
|
||||||
|
/* Py_INCREF boosts _Py_RefTotal if Py_REF_DEBUG is defined */
|
||||||
Py_INCREF(inst);
|
Py_INCREF(inst);
|
||||||
#endif /* !Py_TRACE_REFS */
|
#endif /* !Py_TRACE_REFS */
|
||||||
|
|
||||||
|
/* Save the current exception, if any. */
|
||||||
PyErr_Fetch(&error_type, &error_value, &error_traceback);
|
PyErr_Fetch(&error_type, &error_value, &error_traceback);
|
||||||
|
/* Execute __del__ method, if any. */
|
||||||
if (delstr == NULL)
|
if (delstr == NULL)
|
||||||
delstr = PyString_InternFromString("__del__");
|
delstr = PyString_InternFromString("__del__");
|
||||||
if ((del = instance_getattr2(inst, delstr)) != NULL) {
|
if ((del = instance_getattr2(inst, delstr)) != NULL) {
|
||||||
PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);
|
PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);
|
||||||
if (res == NULL) {
|
if (res == NULL)
|
||||||
PyErr_WriteUnraisable(del);
|
PyErr_WriteUnraisable(del);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
Py_DECREF(res);
|
Py_DECREF(res);
|
||||||
Py_DECREF(del);
|
Py_DECREF(del);
|
||||||
}
|
}
|
||||||
/* Restore the saved exception and undo the temporary revival */
|
/* Restore the saved exception. */
|
||||||
PyErr_Restore(error_type, error_value, error_traceback);
|
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) {
|
if (--inst->ob_refcnt > 0) {
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
inst->ob_type->tp_free--;
|
inst->ob_type->tp_free--;
|
||||||
|
|
@ -525,14 +540,15 @@ instance_dealloc(register PyInstanceObject *inst)
|
||||||
return; /* __del__ added a reference; don't delete now */
|
return; /* __del__ added a reference; don't delete now */
|
||||||
}
|
}
|
||||||
#ifdef Py_TRACE_REFS
|
#ifdef Py_TRACE_REFS
|
||||||
#ifdef COUNT_ALLOCS
|
|
||||||
inst->ob_type->tp_free--; /* compensate for increment in UNREF */
|
|
||||||
#endif
|
|
||||||
_Py_ForgetReference((PyObject *)inst);
|
_Py_ForgetReference((PyObject *)inst);
|
||||||
|
#ifdef COUNT_ALLOCS
|
||||||
|
/* compensate for increment in _Py_ForgetReference */
|
||||||
|
inst->ob_type->tp_free--;
|
||||||
|
#endif
|
||||||
#ifndef WITH_CYCLE_GC
|
#ifndef WITH_CYCLE_GC
|
||||||
inst->ob_type = NULL;
|
inst->ob_type = NULL;
|
||||||
#endif
|
#endif
|
||||||
#endif /* Py_TRACE_REFS */
|
#endif
|
||||||
PyObject_GC_Fini(inst);
|
PyObject_GC_Fini(inst);
|
||||||
Py_DECREF(inst->in_class);
|
Py_DECREF(inst->in_class);
|
||||||
Py_XDECREF(inst->in_dict);
|
Py_XDECREF(inst->in_dict);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue