]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-95324: Emit a warning if an object doesn't call PyObject_GC_UnTrack during dealloc...
authorPablo Galindo Salgado <Pablogsal@gmail.com>
Wed, 27 Jul 2022 15:03:38 +0000 (16:03 +0100)
committerGitHub <noreply@github.com>
Wed, 27 Jul 2022 15:03:38 +0000 (16:03 +0100)
Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst [new file with mode: 0644]
Modules/_abc.c
Modules/_ctypes/cfield.c
Modules/_threadmodule.c
Modules/gcmodule.c
Modules/xxlimited.c
Objects/exceptions.c
Objects/weakrefobject.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst
new file mode 100644 (file)
index 0000000..2503852
--- /dev/null
@@ -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.
index 641d6198d1fec43deeda869cc5a2d30ee975bb8a..b22daa81e3ae1937ecd9a6f453437e7327583a29 100644 (file)
@@ -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);
index c7234fbb18a0fa8e60ae6a717e5e292382903795..13ed8b7eda65557fe036a8e251adab23d55976c5 100644 (file)
@@ -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);
 }
index ace0282ea6fce6cba476da0894fa49136431362e..4ac90dc8068934a7ed324b93ba673c8e3b85b8b3 100644 (file)
@@ -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);
     }
@@ -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
index 3bda6e4bb8c021bd2c5648de6463b88c8213cc06..dcd46feff0cc48bf8cf290f8404f0e1198eb84fc 100644 (file)
@@ -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();
index 5177ecd6b515d71da5f9369c9ecea9f18f8996de..e234504e3319459e437ca2b2001c4ad1964b47f4 100644 (file)
@@ -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);
index e06a8f4173cf8b73137bf0c270bf5095e3cfa154..745b89078ffe199b5ef9319cc5b1d6d3e0df4575 100644 (file)
@@ -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;
     }
@@ -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
@@ -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);
index 2b4361e63ca4133dda4240585bd91d68818acd9c..d26fc9e8d09d71c29992767f029ed5581efa3ff5 100644 (file)
@@ -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);