Skip to content

Commit

Permalink
pythongh-95324: Emit a warning if an object doesn't call PyObject_GC_…
Browse files Browse the repository at this point in the history
…UnTrack during deallocation in debug mode
  • Loading branch information
pablogsal committed Jul 27, 2022
1 parent deacf39 commit 4079c2d
Show file tree
Hide file tree
Showing 8 changed files with 18 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions Modules/_abc.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ abc_data_clear(_abc_data *self)
static void
abc_data_dealloc(_abc_data *self)
{
PyObject_GC_UnTrack(self);
PyTypeObject *tp = Py_TYPE(self);
(void)abc_data_clear(self);
tp->tp_free(self);
Expand Down
1 change: 1 addition & 0 deletions Modules/_ctypes/cfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ PyCField_clear(CFieldObject *self)
static void
PyCField_dealloc(PyObject *self)
{
PyObject_GC_UnTrack(self);
PyCField_clear((CFieldObject *)self);
Py_TYPE(self)->tp_free((PyObject *)self);
}
Expand Down
2 changes: 2 additions & 0 deletions Modules/_threadmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ lock_traverse(lockobject *self, visitproc visit, void *arg)
static void
lock_dealloc(lockobject *self)
{
PyObject_GC_UnTrack(self);
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
}
Expand Down Expand Up @@ -333,6 +334,7 @@ rlock_traverse(rlockobject *self, visitproc visit, void *arg)
static void
rlock_dealloc(rlockobject *self)
{
PyObject_GC_UnTrack(self);
if (self->in_weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
/* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
Expand Down
7 changes: 7 additions & 0 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2347,6 +2347,13 @@ PyObject_GC_Del(void *op)
size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type);
PyGC_Head *g = AS_GC(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);
}
GCState *gcstate = get_gc_state();
Expand Down
1 change: 1 addition & 0 deletions Modules/xxlimited.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ Xxo_finalize(PyObject *self_obj)
static void
Xxo_dealloc(PyObject *self)
{
PyObject_GC_UnTrack(self);
Xxo_finalize(self);
PyTypeObject *tp = Py_TYPE(self);
freefunc free = PyType_GetSlot(tp, Py_tp_free);
Expand Down
5 changes: 3 additions & 2 deletions Objects/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -3214,6 +3214,7 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self = state->memerrors_freelist;
self->args = PyTuple_New(0);
/* This shouldn't happen since the empty tuple is persistent */

if (self->args == NULL) {
return NULL;
}
Expand All @@ -3229,6 +3230,8 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void
MemoryError_dealloc(PyBaseExceptionObject *self)
{
_PyObject_GC_UNTRACK(self);

BaseException_clear(self);

/* If this is a subclass of MemoryError, we don't need to
Expand All @@ -3238,8 +3241,6 @@ MemoryError_dealloc(PyBaseExceptionObject *self)
return;
}

_PyObject_GC_UNTRACK(self);

struct _Py_exc_state *state = get_exc_state();
if (state->memerrors_numfree >= MEMERRORS_SAVE) {
Py_TYPE(self)->tp_free((PyObject *)self);
Expand Down
1 change: 1 addition & 0 deletions Objects/weakrefobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ proxy_bool(PyWeakReference *proxy)
static void
proxy_dealloc(PyWeakReference *self)
{
PyObject_GC_UnTrack(self);
if (self->wr_callback != NULL)
PyObject_GC_UnTrack((PyObject *)self);
clear_weakref(self);
Expand Down

0 comments on commit 4079c2d

Please sign in to comment.