[Python-checkins] gh-95324: Emit a warning if an object doesn't call PyObject_GC_UnTrack during deallocation in debug mode (#95325)

pablogsal webhook-mailer at python.org
Wed Jul 27 11:04:04 EDT 2022


https://github.com/python/cpython/commit/f40bc7fa49f8d137f9b38f7a14569e9a9bdbed07
commit: f40bc7fa49f8d137f9b38f7a14569e9a9bdbed07
branch: main
author: Pablo Galindo Salgado <Pablogsal at gmail.com>
committer: pablogsal <Pablogsal at gmail.com>
date: 2022年07月27日T16:03:38+01:00
summary:
gh-95324: Emit a warning if an object doesn't call PyObject_GC_UnTrack during deallocation in debug mode (#95325)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst
M Modules/_abc.c
M Modules/_ctypes/cfield.c
M Modules/_threadmodule.c
M Modules/gcmodule.c
M Modules/xxlimited.c
M Objects/exceptions.c
M 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
index 0000000000000..250385270e948
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst	
@@ -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.
diff --git a/Modules/_abc.c b/Modules/_abc.c
index 641d6198d1fec..b22daa81e3ae1 100644
--- a/Modules/_abc.c
+++ b/Modules/_abc.c
@@ -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);
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index c7234fbb18a0f..13ed8b7eda655 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -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);
 }
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index ace0282ea6fce..4ac90dc806893 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -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
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 3bda6e4bb8c02..dcd46feff0cc4 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -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();
diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c
index 5177ecd6b515d..e234504e33194 100644
--- a/Modules/xxlimited.c
+++ b/Modules/xxlimited.c
@@ -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);
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index e06a8f4173cf8..745b89078ffe1 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -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);
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index 2b4361e63ca41..d26fc9e8d09d7 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -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);


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /