mirror of
https://github.com/python/cpython
synced 2024-09-16 00:48:28 +00:00
gh-95324: Emit a warning if an object doesn't call PyObject_GC_UnTrack during deallocation in debug mode (#95325)
This commit is contained in:
parent
2833f3798d
commit
f40bc7fa49
|
@ -0,0 +1,2 @@
|
||||||
|
Emit a warning in debug mode if an object does not call
|
||||||
|
:c:func:`PyObject_GC_UnTrack` before deallocation. Patch by Pablo Galindo.
|
|
@ -63,6 +63,7 @@ abc_data_clear(_abc_data *self)
|
||||||
static void
|
static void
|
||||||
abc_data_dealloc(_abc_data *self)
|
abc_data_dealloc(_abc_data *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
PyTypeObject *tp = Py_TYPE(self);
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
(void)abc_data_clear(self);
|
(void)abc_data_clear(self);
|
||||||
tp->tp_free(self);
|
tp->tp_free(self);
|
||||||
|
|
|
@ -279,6 +279,7 @@ PyCField_clear(CFieldObject *self)
|
||||||
static void
|
static void
|
||||||
PyCField_dealloc(PyObject *self)
|
PyCField_dealloc(PyObject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
PyCField_clear((CFieldObject *)self);
|
PyCField_clear((CFieldObject *)self);
|
||||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ lock_traverse(lockobject *self, visitproc visit, void *arg)
|
||||||
static void
|
static void
|
||||||
lock_dealloc(lockobject *self)
|
lock_dealloc(lockobject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
if (self->in_weakreflist != NULL) {
|
if (self->in_weakreflist != NULL) {
|
||||||
PyObject_ClearWeakRefs((PyObject *) self);
|
PyObject_ClearWeakRefs((PyObject *) self);
|
||||||
}
|
}
|
||||||
|
@ -333,6 +334,7 @@ rlock_traverse(rlockobject *self, visitproc visit, void *arg)
|
||||||
static void
|
static void
|
||||||
rlock_dealloc(rlockobject *self)
|
rlock_dealloc(rlockobject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
if (self->in_weakreflist != NULL)
|
if (self->in_weakreflist != NULL)
|
||||||
PyObject_ClearWeakRefs((PyObject *) self);
|
PyObject_ClearWeakRefs((PyObject *) self);
|
||||||
/* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
|
/* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
|
||||||
|
|
|
@ -2347,6 +2347,13 @@ PyObject_GC_Del(void *op)
|
||||||
size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type);
|
size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type);
|
||||||
PyGC_Head *g = AS_GC(op);
|
PyGC_Head *g = AS_GC(op);
|
||||||
if (_PyObject_GC_IS_TRACKED(op)) {
|
if (_PyObject_GC_IS_TRACKED(op)) {
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0,
|
||||||
|
"gc", NULL, "Object of type %s is not untracked before destruction",
|
||||||
|
((PyObject*)op)->ob_type->tp_name)) {
|
||||||
|
PyErr_WriteUnraisable(NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
gc_list_remove(g);
|
gc_list_remove(g);
|
||||||
}
|
}
|
||||||
GCState *gcstate = get_gc_state();
|
GCState *gcstate = get_gc_state();
|
||||||
|
|
|
@ -138,6 +138,7 @@ Xxo_finalize(PyObject *self_obj)
|
||||||
static void
|
static void
|
||||||
Xxo_dealloc(PyObject *self)
|
Xxo_dealloc(PyObject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
Xxo_finalize(self);
|
Xxo_finalize(self);
|
||||||
PyTypeObject *tp = Py_TYPE(self);
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
freefunc free = PyType_GetSlot(tp, Py_tp_free);
|
freefunc free = PyType_GetSlot(tp, Py_tp_free);
|
||||||
|
|
|
@ -3214,6 +3214,7 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
self = state->memerrors_freelist;
|
self = state->memerrors_freelist;
|
||||||
self->args = PyTuple_New(0);
|
self->args = PyTuple_New(0);
|
||||||
/* This shouldn't happen since the empty tuple is persistent */
|
/* This shouldn't happen since the empty tuple is persistent */
|
||||||
|
|
||||||
if (self->args == NULL) {
|
if (self->args == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3229,6 +3230,8 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
static void
|
static void
|
||||||
MemoryError_dealloc(PyBaseExceptionObject *self)
|
MemoryError_dealloc(PyBaseExceptionObject *self)
|
||||||
{
|
{
|
||||||
|
_PyObject_GC_UNTRACK(self);
|
||||||
|
|
||||||
BaseException_clear(self);
|
BaseException_clear(self);
|
||||||
|
|
||||||
/* If this is a subclass of MemoryError, we don't need to
|
/* If this is a subclass of MemoryError, we don't need to
|
||||||
|
@ -3238,8 +3241,6 @@ MemoryError_dealloc(PyBaseExceptionObject *self)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyObject_GC_UNTRACK(self);
|
|
||||||
|
|
||||||
struct _Py_exc_state *state = get_exc_state();
|
struct _Py_exc_state *state = get_exc_state();
|
||||||
if (state->memerrors_numfree >= MEMERRORS_SAVE) {
|
if (state->memerrors_numfree >= MEMERRORS_SAVE) {
|
||||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||||
|
|
|
@ -558,6 +558,7 @@ proxy_bool(PyWeakReference *proxy)
|
||||||
static void
|
static void
|
||||||
proxy_dealloc(PyWeakReference *self)
|
proxy_dealloc(PyWeakReference *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
if (self->wr_callback != NULL)
|
if (self->wr_callback != NULL)
|
||||||
PyObject_GC_UnTrack((PyObject *)self);
|
PyObject_GC_UnTrack((PyObject *)self);
|
||||||
clear_weakref(self);
|
clear_weakref(self);
|
||||||
|
|
Loading…
Reference in a new issue