https://github.com/python/cpython/commit/e3a277c8d8aab08177fc548fde53c671f994c31a
commit: e3a277c8d8aab08177fc548fde53c671f994c31a
branch: 3.13
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2025-07-01T11:26:52+02:00
summary:

[3.13] gh-135607: remove null checking of weakref list in dealloc of extension 
modules and objects (#135614) (#136126)

gh-135607: remove null checking of weakref list in dealloc of extension modules 
and objects (#135614)

(cherry picked from commit b1056c2a446b43452e457d5fd5f1bde66afd3883)

Co-authored-by: Xuanteng Huang <[email protected]>
Co-authored-by: Kumar Aditya <[email protected]>

files:
A Misc/NEWS.d/next/Core and 
Builtins/2025-06-17-22-34-58.gh-issue-135607.ucsLVu.rst
M Include/internal/pycore_weakref.h
M Modules/_collectionsmodule.c
M Modules/_elementtree.c
M Modules/_functoolsmodule.c
M Modules/_io/bufferedio.c
M Modules/_io/bytesio.c
M Modules/_io/fileio.c
M Modules/_io/iobase.c
M Modules/_io/stringio.c
M Modules/_io/textio.c
M Modules/_io/winconsoleio.c
M Modules/_queuemodule.c
M Modules/_sqlite/blob.c
M Modules/_sqlite/cursor.c
M Modules/_sre/sre.c
M Modules/_struct.c
M Modules/_threadmodule.c
M Modules/_zoneinfo.c
M Modules/arraymodule.c
M Modules/mmapmodule.c
M Objects/classobject.c
M Objects/codeobject.c
M Objects/funcobject.c
M Objects/genericaliasobject.c
M Objects/genobject.c
M Objects/methodobject.c
M Objects/moduleobject.c
M Objects/odictobject.c
M Objects/picklebufobject.c
M Objects/setobject.c

diff --git a/Include/internal/pycore_weakref.h 
b/Include/internal/pycore_weakref.h
index 94aadb2c1547dd..ff1395ea837dcb 100644
--- a/Include/internal/pycore_weakref.h
+++ b/Include/internal/pycore_weakref.h
@@ -29,6 +29,12 @@ extern "C" {
     PyMutex_LockFlags(wr->weakrefs_lock, _Py_LOCK_DONT_DETACH)
 #define UNLOCK_WEAKREFS_FOR_WR(wr) PyMutex_Unlock(wr->weakrefs_lock)
 
+#define FT_CLEAR_WEAKREFS(obj, weakref_list)    \
+    do {                                        \
+        assert(Py_REFCNT(obj) == 0);            \
+        PyObject_ClearWeakRefs(obj);            \
+    } while (0)
+
 #else
 
 #define LOCK_WEAKREFS(obj)
@@ -37,6 +43,14 @@ extern "C" {
 #define LOCK_WEAKREFS_FOR_WR(wr)
 #define UNLOCK_WEAKREFS_FOR_WR(wr)
 
+#define FT_CLEAR_WEAKREFS(obj, weakref_list)        \
+    do {                                            \
+        assert(Py_REFCNT(obj) == 0);                \
+        if (weakref_list != NULL) {                 \
+            PyObject_ClearWeakRefs(obj);            \
+        }                                           \
+    } while (0)
+
 #endif
 
 static inline int _is_dead(PyObject *obj)
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2025-06-17-22-34-58.gh-issue-135607.ucsLVu.rst b/Misc/NEWS.d/next/Core 
and Builtins/2025-06-17-22-34-58.gh-issue-135607.ucsLVu.rst
new file mode 100644
index 00000000000000..859259a9ace758
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2025-06-17-22-34-58.gh-issue-135607.ucsLVu.rst 
@@ -0,0 +1,2 @@
+Fix potential :mod:`weakref` races in an object's destructor on the 
:term:`free threaded <free
+threading>` build.
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index c821f18b1708e1..2c30e5c70a6cc2 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -5,6 +5,7 @@
 #include "pycore_moduleobject.h"  // _PyModule_GetState()
 #include "pycore_pyatomic_ft_wrappers.h"
 #include "pycore_typeobject.h"    // _PyType_GetModuleState()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>
 
@@ -1521,8 +1522,7 @@ deque_dealloc(dequeobject *deque)
     Py_ssize_t i;
 
     PyObject_GC_UnTrack(deque);
-    if (deque->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) deque);
+    FT_CLEAR_WEAKREFS((PyObject*)deque, deque->weakreflist);
     if (deque->leftblock != NULL) {
         deque_clear(deque);
         assert(deque->leftblock != NULL);
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 47a601b270aff6..3926ef3ef835e1 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -18,6 +18,7 @@
 #include "Python.h"
 #include "pycore_import.h"        // _PyImport_GetModuleAttrString()
 #include "pycore_pyhash.h"        // _Py_HashSecret
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>               // offsetof()
 #include "expat.h"
@@ -688,8 +689,7 @@ element_dealloc(ElementObject* self)
     PyObject_GC_UnTrack(self);
     Py_TRASHCAN_BEGIN(self, element_dealloc)
 
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject*)self, self->weakreflist);
 
     /* element_gc_clear clears all references and deallocates extra
     */
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 9e140a1a580832..7add3987cd02f1 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -6,6 +6,7 @@
 #include "pycore_object.h"        // _PyObject_GC_TRACK
 #include "pycore_pystate.h"       // _PyThreadState_GET()
 #include "pycore_tuple.h"         // _PyTuple_ITEMS()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 
 #include "clinic/_functoolsmodule.c.h"
@@ -189,9 +190,7 @@ partial_dealloc(partialobject *pto)
     PyTypeObject *tp = Py_TYPE(pto);
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(pto);
-    if (pto->weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject *) pto);
-    }
+    FT_CLEAR_WEAKREFS((PyObject*)pto, pto->weakreflist);
     (void)partial_clear(pto);
     tp->tp_free(pto);
     Py_DECREF(tp);
@@ -1317,9 +1316,7 @@ lru_cache_dealloc(lru_cache_object *obj)
     PyTypeObject *tp = Py_TYPE(obj);
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(obj);
-    if (obj->weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject*)obj);
-    }
+    FT_CLEAR_WEAKREFS((PyObject*)obj, obj->weakreflist);
 
     (void)lru_cache_tp_clear(obj);
     tp->tp_free(obj);
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 050878c6da6ec3..65d69d0d5e13d0 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -12,6 +12,7 @@
 #include "pycore_object.h"              // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"            // _Py_FatalErrorFormat()
 #include "pycore_pylifecycle.h"         // _Py_IsInterpreterFinalizing()
+#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
 
 #include "_iomodule.h"
 
@@ -416,8 +417,7 @@ buffered_dealloc(buffered *self)
         return;
     _PyObject_GC_UNTRACK(self);
     self->ok = 0;
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)self);
+    FT_CLEAR_WEAKREFS((PyObject*)self, self->weakreflist);
     if (self->buffer) {
         PyMem_Free(self->buffer);
         self->buffer = NULL;
@@ -2299,8 +2299,7 @@ bufferedrwpair_dealloc(rwpair *self)
 {
     PyTypeObject *tp = Py_TYPE(self);
     _PyObject_GC_UNTRACK(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)self);
+    FT_CLEAR_WEAKREFS((PyObject *)self, self->weakreflist);
     (void)bufferedrwpair_clear(self);
     tp->tp_free((PyObject *) self);
     Py_DECREF(tp);
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index fb66d3db0f7a1f..0a96885b31b927 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -1,6 +1,7 @@
 #include "Python.h"
 #include "pycore_object.h"
 #include "pycore_sysmodule.h"     // _PySys_GetSizeOf()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>               // offsetof()
 #include "_iomodule.h"
@@ -894,8 +895,7 @@ bytesio_dealloc(bytesio *self)
     }
     Py_CLEAR(self->buf);
     Py_CLEAR(self->dict);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     tp->tp_free(self);
     Py_DECREF(tp);
 }
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 545eb4acf9b10e..65957a713b6c35 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -4,6 +4,7 @@
 #include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
 #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stdbool.h>              // bool
 #ifdef HAVE_UNISTD_H
@@ -545,8 +546,7 @@ fileio_dealloc(fileio *self)
     if (_PyIOBase_finalize((PyObject *) self) < 0)
         return;
     _PyObject_GC_UNTRACK(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     (void)fileio_clear(self);
     tp->tp_free((PyObject *)self);
     Py_DECREF(tp);
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index 184e0b7d1aa7f1..12f8b430f9ceb1 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -13,6 +13,7 @@
 #include "pycore_long.h"          // _PyLong_GetOne()
 #include "pycore_object.h"        // _PyType_HasFeature()
 #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>               // offsetof()
 #include "_iomodule.h"
@@ -376,8 +377,7 @@ iobase_dealloc(iobase *self)
     }
     PyTypeObject *tp = Py_TYPE(self);
     _PyObject_GC_UNTRACK(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     Py_CLEAR(self->dict);
     tp->tp_free((PyObject *)self);
     Py_DECREF(tp);
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index e39289a02bda0f..e4c39a0a90507c 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -1,6 +1,7 @@
 #include "Python.h"
 #include <stddef.h>               // offsetof()
 #include "pycore_object.h"
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 #include "_iomodule.h"
 
 /* Implementation note: the buffer is always at least one character longer
@@ -617,9 +618,7 @@ stringio_dealloc(stringio *self)
     }
     _PyUnicodeWriter_Dealloc(&self->writer);
     (void)stringio_clear(self);
-    if (self->weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject *) self);
-    }
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     tp->tp_free(self);
     Py_DECREF(tp);
 }
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 963dbdd9b1452f..c1d8e16e12c722 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -15,6 +15,7 @@
 #include "pycore_object.h"            // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"          // _PyErr_ChainExceptions1()
 #include "pycore_pystate.h"           // _PyInterpreterState_GET()
+#include "pycore_weakref.h"           // FT_CLEAR_WEAKREFS()
 
 #include "_iomodule.h"
 
@@ -1460,8 +1461,7 @@ textiowrapper_dealloc(textio *self)
         return;
     self->ok = 0;
     _PyObject_GC_UNTRACK(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)self);
+    FT_CLEAR_WEAKREFS((PyObject *)self, self->weakreflist);
     (void)textiowrapper_clear(self);
     tp->tp_free((PyObject *)self);
     Py_DECREF(tp);
diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c
index 6e97403ba1400b..008f8bf118870f 100644
--- a/Modules/_io/winconsoleio.c
+++ b/Modules/_io/winconsoleio.c
@@ -10,6 +10,7 @@
 #include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
 #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #ifdef HAVE_WINDOWS_CONSOLE_IO
 
@@ -514,8 +515,7 @@ winconsoleio_dealloc(winconsoleio *self)
     if (_PyIOBase_finalize((PyObject *) self) < 0)
         return;
     _PyObject_GC_UNTRACK(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     Py_CLEAR(self->dict);
     tp->tp_free((PyObject *)self);
     Py_DECREF(tp);
diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c
index aee8db802d8c3f..5c995cf68334e6 100644
--- a/Modules/_queuemodule.c
+++ b/Modules/_queuemodule.c
@@ -7,6 +7,7 @@
 #include "pycore_moduleobject.h"  // _PyModule_GetState()
 #include "pycore_parking_lot.h"
 #include "pycore_time.h"          // _PyTime_FromSecondsObject()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stdbool.h>
 #include <stddef.h>               // offsetof()
@@ -217,8 +218,7 @@ simplequeue_dealloc(simplequeueobject *self)
 
     PyObject_GC_UnTrack(self);
     (void)simplequeue_clear(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     Py_TYPE(self)->tp_free(self);
     Py_DECREF(tp);
 }
diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c
index 7deb58bf1b9b82..6ad3f9c0968313 100644
--- a/Modules/_sqlite/blob.c
+++ b/Modules/_sqlite/blob.c
@@ -4,6 +4,7 @@
 
 #include "blob.h"
 #include "util.h"
+#include "pycore_weakref.h"    // FT_CLEAR_WEAKREFS()
 
 #define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
 #include "clinic/blob.c.h"
@@ -51,9 +52,7 @@ blob_dealloc(pysqlite_Blob *self)
 
     close_blob(self);
 
-    if (self->in_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject*)self);
-    }
+    FT_CLEAR_WEAKREFS((PyObject*)self, self->in_weakreflist);
     tp->tp_clear((PyObject *)self);
     tp->tp_free(self);
     Py_DECREF(tp);
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 950596ea82b568..f9eb31f6faf47f 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -31,6 +31,7 @@
 #include "util.h"
 
 #include "pycore_pyerrors.h"      // _PyErr_FormatFromCause()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 typedef enum {
     TYPE_LONG,
@@ -180,9 +181,7 @@ cursor_dealloc(pysqlite_Cursor *self)
 {
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
-    if (self->in_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject*)self);
-    }
+    FT_CLEAR_WEAKREFS((PyObject*)self, self->in_weakreflist);
     tp->tp_clear((PyObject *)self);
     tp->tp_free(self);
     Py_DECREF(tp);
diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c
index 608a0ccb11535c..898ebbfe89bcd2 100644
--- a/Modules/_sre/sre.c
+++ b/Modules/_sre/sre.c
@@ -43,6 +43,7 @@ static const char copyright[] =
 #include "pycore_dict.h"             // _PyDict_Next()
 #include "pycore_long.h"             // _PyLong_GetZero()
 #include "pycore_moduleobject.h"     // _PyModule_GetState()
+#include "pycore_weakref.h"          // FT_CLEAR_WEAKREFS()
 
 #include "sre.h"                     // SRE_CODE
 
@@ -729,9 +730,7 @@ pattern_dealloc(PatternObject* self)
     PyTypeObject *tp = Py_TYPE(self);
 
     PyObject_GC_UnTrack(self);
-    if (self->weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject *) self);
-    }
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     (void)pattern_clear(self);
     tp->tp_free(self);
     Py_DECREF(tp);
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 30b8bd9600b378..a9f8fa4bbdeca3 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -11,6 +11,7 @@
 #include "pycore_bytesobject.h"   // _PyBytesWriter
 #include "pycore_long.h"          // _PyLong_AsByteArray()
 #include "pycore_moduleobject.h"  // _PyModule_GetState()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>               // offsetof()
 
@@ -1639,8 +1640,7 @@ s_dealloc(PyStructObject *s)
 {
     PyTypeObject *tp = Py_TYPE(s);
     PyObject_GC_UnTrack(s);
-    if (s->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)s);
+    FT_CLEAR_WEAKREFS((PyObject *)s, s->weakreflist);
     if (s->s_codes != NULL) {
         PyMem_Free(s->s_codes);
     }
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 52bb45f1891ac3..b390678854a850 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -1367,8 +1367,7 @@ typedef struct {
 static void
 localdummy_dealloc(localdummyobject *self)
 {
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject *) self, self->weakreflist);
     PyTypeObject *tp = Py_TYPE(self);
     tp->tp_free((PyObject*)self);
     Py_DECREF(tp);
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index c5292575c22f23..63643b7bfc7d93 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -6,6 +6,7 @@
 #include "pycore_critical_section.h"  // 
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED()
 #include "pycore_long.h"          // _PyLong_GetOne()
 #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include "datetime.h"             // PyDateTime_TZInfo
 
@@ -368,9 +369,7 @@ zoneinfo_dealloc(PyObject *obj_self)
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
 
-    if (self->weakreflist != NULL) {
-        PyObject_ClearWeakRefs(obj_self);
-    }
+    FT_CLEAR_WEAKREFS(obj_self, self->weakreflist);
 
     if (self->trans_list_utc != NULL) {
         PyMem_Free(self->trans_list_utc);
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 62a3cca1e948ba..e4b11f2a041568 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -13,6 +13,7 @@
 #include "pycore_ceval.h"         // _PyEval_GetBuiltin()
 #include "pycore_modsupport.h"    // _PyArg_NoKeywords()
 #include "pycore_moduleobject.h"  // _PyModule_GetState()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>               // offsetof()
 #include <stdbool.h>
@@ -708,8 +709,7 @@ array_dealloc(arrayobject *op)
     PyTypeObject *tp = Py_TYPE(op);
     PyObject_GC_UnTrack(op);
 
-    if (op->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) op);
+    FT_CLEAR_WEAKREFS((PyObject *) op, op->weakreflist);
     if (op->ob_item != NULL)
         PyMem_Free(op->ob_item);
     tp->tp_free(op);
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 99a85e9e49ad47..4cc888004c3c27 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -26,6 +26,7 @@
 #include "pycore_abstract.h"      // _Py_convert_optional_to_ssize_t()
 #include "pycore_bytesobject.h"   // _PyBytes_Find()
 #include "pycore_fileutils.h"     // _Py_stat_struct
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include <stddef.h>               // offsetof()
 #ifndef MS_WINDOWS
@@ -161,8 +162,7 @@ mmap_object_dealloc(mmap_object *m_obj)
     Py_END_ALLOW_THREADS
 #endif /* UNIX */
 
-    if (m_obj->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) m_obj);
+    FT_CLEAR_WEAKREFS((PyObject *) m_obj, m_obj->weakreflist);
 
     tp->tp_free(m_obj);
     Py_DECREF(tp);
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 69a7d5f046e30d..c8f215a2b05704 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -6,6 +6,7 @@
 #include "pycore_object.h"
 #include "pycore_pyerrors.h"
 #include "pycore_pystate.h"       // _PyThreadState_GET()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 
 #include "clinic/classobject.c.h"
@@ -238,8 +239,7 @@ static void
 method_dealloc(PyMethodObject *im)
 {
     _PyObject_GC_UNTRACK(im);
-    if (im->im_weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)im);
+    FT_CLEAR_WEAKREFS((PyObject*)im, im->im_weakreflist);
     Py_DECREF(im->im_func);
     Py_XDECREF(im->im_self);
     PyObject_GC_Del(im);
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index bfa679fcf6ee3e..bdf6ee95a8b3a3 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -12,6 +12,7 @@
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 #include "pycore_setobject.h"     // _PySet_NextEntry()
 #include "pycore_tuple.h"         // _PyTuple_ITEMS()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 #include "clinic/codeobject.c.h"
 
 #include <stdbool.h>
@@ -1927,9 +1928,7 @@ code_dealloc(PyCodeObject *co)
         Py_XDECREF(co->_co_cached->_co_varnames);
         PyMem_Free(co->_co_cached);
     }
-    if (co->co_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject*)co);
-    }
+    FT_CLEAR_WEAKREFS((PyObject*)co, co->co_weakreflist);
     free_monitoring_data(co->_co_monitoring);
     PyObject_Free(co);
 }
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 3d93673e1863d8..caa58ad0f18e61 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -8,6 +8,7 @@
 #include "pycore_modsupport.h"          // _PyArg_NoKeywords()
 #include "pycore_object.h"              // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"            // _PyErr_Occurred()
+#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
 
 
 static const char *
@@ -1034,9 +1035,7 @@ func_dealloc(PyFunctionObject *op)
         return;
     }
     _PyObject_GC_UNTRACK(op);
-    if (op->func_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject *) op);
-    }
+    FT_CLEAR_WEAKREFS((PyObject *) op, op->func_weakreflist);
     _PyFunction_SetVersion(op, 0);
     (void)func_clear(op);
     // These aren't cleared by func_clear().
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index 3c64e75fca8a2e..efe18adb4a8d10 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -5,6 +5,7 @@
 #include "pycore_modsupport.h"    // _PyArg_NoKeywords()
 #include "pycore_object.h"
 #include "pycore_unionobject.h"   // _Py_union_type_or, _PyGenericAlias_Check
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 
 #include <stdbool.h>
@@ -31,9 +32,7 @@ ga_dealloc(PyObject *self)
     gaobject *alias = (gaobject *)self;
 
     _PyObject_GC_UNTRACK(self);
-    if (alias->weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject *)alias);
-    }
+    FT_CLEAR_WEAKREFS((PyObject *)alias, alias->weakreflist);
     Py_XDECREF(alias->origin);
     Py_XDECREF(alias->args);
     Py_XDECREF(alias->parameters);
diff --git a/Objects/genobject.c b/Objects/genobject.c
index dedf9e21e9a089..c5156d84185ebd 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -14,6 +14,7 @@
 #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_*
 #include "pycore_pyerrors.h"      // _PyErr_ClearExcState()
 #include "pycore_pystate.h"       // _PyThreadState_GET()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include "pystats.h"
 
@@ -138,8 +139,7 @@ gen_dealloc(PyGenObject *gen)
 
     _PyObject_GC_UNTRACK(gen);
 
-    if (gen->gi_weakreflist != NULL)
-        PyObject_ClearWeakRefs(self);
+    FT_CLEAR_WEAKREFS(self, gen->gi_weakreflist);
 
     _PyObject_GC_TRACK(self);
 
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index d6773a264101dc..8fe4c0e0d4af36 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -7,6 +7,7 @@
 #include "pycore_object.h"
 #include "pycore_pyerrors.h"
 #include "pycore_pystate.h"       // _PyThreadState_GET()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 
 /* undefine macro trampoline to PyCFunction_NewEx */
@@ -162,9 +163,7 @@ meth_dealloc(PyCFunctionObject *m)
     // call PyObject_GC_UnTrack twice on an object.
     PyObject_GC_UnTrack(m);
     Py_TRASHCAN_BEGIN(m, meth_dealloc);
-    if (m->m_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject*) m);
-    }
+    FT_CLEAR_WEAKREFS((PyObject*) m, m->m_weakreflist);
     // Dereference class before m_self: PyCFunction_GET_CLASS accesses
     // PyMethodDef m_ml, which could be kept alive by m_self
     Py_XDECREF(PyCFunction_GET_CLASS(m));
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 37faaaf7d19303..d787f29004550b 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -11,6 +11,7 @@
 #include "pycore_pyerrors.h"      // _PyErr_FormatFromCause()
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 #include "pycore_sysmodule.h"     // _PySys_GetOptionalAttrString()
+#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
 
 #include "osdefs.h"               // MAXPATHLEN
 
@@ -766,8 +767,7 @@ module_dealloc(PyModuleObject *m)
     if (verbose && m->md_name) {
         PySys_FormatStderr("# destroy %U\n", m->md_name);
     }
-    if (m->md_weaklist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) m);
+    FT_CLEAR_WEAKREFS((PyObject *) m, m->md_weaklist);
     /* bpo-39824: Don't call m_free() if m_size > 0 and md_state=NULL */
     if (m->md_def && m->md_def->m_free
         && (m->md_def->m_size <= 0 || m->md_state != NULL))
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 858f0cbaf9ee00..cfe8bb49f7a3ad 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -472,6 +472,7 @@ Potential Optimizations
 #include "pycore_object.h"           // _PyObject_GC_UNTRACK()
 #include "pycore_pyerrors.h"         // _PyErr_ChainExceptions1()
 #include <stddef.h>                  // offsetof()
+#include "pycore_weakref.h"          // FT_CLEAR_WEAKREFS()
 
 #include "clinic/odictobject.c.h"
 
@@ -1383,8 +1384,7 @@ odict_dealloc(PyODictObject *self)
     Py_TRASHCAN_BEGIN(self, odict_dealloc)
 
     Py_XDECREF(self->od_inst_dict);
-    if (self->od_weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)self);
+    FT_CLEAR_WEAKREFS((PyObject*)self, self->od_weakreflist);
 
     _odict_clear_nodes(self);
     PyDict_Type.tp_dealloc((PyObject *)self);
diff --git a/Objects/picklebufobject.c b/Objects/picklebufobject.c
index ca83a0a0806ce1..0de5245585e6f0 100644
--- a/Objects/picklebufobject.c
+++ b/Objects/picklebufobject.c
@@ -1,6 +1,7 @@
 /* PickleBuffer object implementation */
 
 #include "Python.h"
+#include "pycore_weakref.h"     // FT_CLEAR_WEAKREFS()
 #include <stddef.h>
 
 typedef struct {
@@ -108,8 +109,7 @@ static void
 picklebuf_dealloc(PyPickleBufferObject *self)
 {
     PyObject_GC_UnTrack(self);
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+    FT_CLEAR_WEAKREFS((PyObject*)self, self->weakreflist);
     PyBuffer_Release(&self->view);
     Py_TYPE(self)->tp_free((PyObject *) self);
 }
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 7c5d6eb34cae08..5ec627558abbfe 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -40,6 +40,7 @@
 #include "pycore_pyatomic_ft_wrappers.h"  // FT_ATOMIC_LOAD_SSIZE_RELAXED()
 #include "pycore_pyerrors.h"            // _PyErr_SetKeyError()
 #include "pycore_setobject.h"           // _PySet_NextEntry() definition
+#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
 #include <stddef.h>                     // offsetof()
 #include "clinic/setobject.c.h"
 
@@ -498,8 +499,7 @@ set_dealloc(PySetObject *so)
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(so);
     Py_TRASHCAN_BEGIN(so, set_dealloc)
-    if (so->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) so);
+    FT_CLEAR_WEAKREFS((PyObject *) so, so->weakreflist);
 
     for (entry = so->table; used > 0; entry++) {
         if (entry->key && entry->key != dummy) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to