]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-135607: remove null checking of weakref list in dealloc of extension module...
authorVictor Stinner <vstinner@python.org>
Tue, 1 Jul 2025 09:26:52 +0000 (11:26 +0200)
committerGitHub <noreply@github.com>
Tue, 1 Jul 2025 09:26:52 +0000 (11:26 +0200)
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 <44627253+xuantengh@users.noreply.github.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
31 files changed:
Include/internal/pycore_weakref.h
Misc/NEWS.d/next/Core and Builtins/2025-06-17-22-34-58.gh-issue-135607.ucsLVu.rst [new file with mode: 0644]
Modules/_collectionsmodule.c
Modules/_elementtree.c
Modules/_functoolsmodule.c
Modules/_io/bufferedio.c
Modules/_io/bytesio.c
Modules/_io/fileio.c
Modules/_io/iobase.c
Modules/_io/stringio.c
Modules/_io/textio.c
Modules/_io/winconsoleio.c
Modules/_queuemodule.c
Modules/_sqlite/blob.c
Modules/_sqlite/cursor.c
Modules/_sre/sre.c
Modules/_struct.c
Modules/_threadmodule.c
Modules/_zoneinfo.c
Modules/arraymodule.c
Modules/mmapmodule.c
Objects/classobject.c
Objects/codeobject.c
Objects/funcobject.c
Objects/genericaliasobject.c
Objects/genobject.c
Objects/methodobject.c
Objects/moduleobject.c
Objects/odictobject.c
Objects/picklebufobject.c
Objects/setobject.c

index 94aadb2c1547dd3e763f017794af7fe73cd8f822..ff1395ea837dcb832761afb5ef3c1d4fb430bfb3 100644 (file)
@@ -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 (file)
index 0000000..859259a
--- /dev/null
@@ -0,0 +1,2 @@
+Fix potential :mod:`weakref` races in an object's destructor on the :term:`free threaded <free
+threading>` build.
index c821f18b1708e110c8e1a4fbb32f6be11bc061b6..2c30e5c70a6cc2fa5317e20bd8ca4de0e8c6890c 100644 (file)
@@ -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);
index 47a601b270aff63f5c76c7bd3bf227ffe9506351..3926ef3ef835e18d959d07304b58b31cea78bd2b 100644 (file)
@@ -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
     */
index 9e140a1a580832e052178262cf07856754a474c3..7add3987cd02f1ec37bcbf287511d868bc99efc5 100644 (file)
@@ -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);
index 050878c6da6ec3f91cd278ed475ea0e243a292db..65d69d0d5e13d083ea27f23469f56c81081fe2f1 100644 (file)
@@ -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);
index fb66d3db0f7a1f37411dca7b5b759d0564eeefd6..0a96885b31b927e0ce17b24d21a2555ab5dde8f7 100644 (file)
@@ -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);
 }
index 545eb4acf9b10e683a085051c592afe4dad357ac..65957a713b6c3567e0f859de5cd7d8da3c523fef 100644 (file)
@@ -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);
index 184e0b7d1aa7f1a12ca62e594cec1336fe0c79f9..12f8b430f9ceb1c970078df7bbb58bb9b82104e0 100644 (file)
@@ -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);
index e39289a02bda0f0bf1e511dfe2e76ee93a65e382..e4c39a0a90507c6cc0af282aacf21f3e9c66b4f8 100644 (file)
@@ -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);
 }
index 963dbdd9b1452fd711df577efb4f3419f4b7794d..c1d8e16e12c72280f3f87abb5659bff46dd10f55 100644 (file)
@@ -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);
index 6e97403ba1400b1e7d1397f285fa7e1559e71569..008f8bf118870f27da581652224d2475695530cd 100644 (file)
@@ -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);
index aee8db802d8c3f57bb5b290d223b1099ce426603..5c995cf68334e62536e2ad0f11aba316fc4ee90e 100644 (file)
@@ -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);
 }
index 7deb58bf1b9b82fda935d50e6cf9d823aafd2e03..6ad3f9c0968313fc936a55fb74f9294a3cb727f6 100644 (file)
@@ -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);
index 950596ea82b5683c4868f37e2c3905f801636f77..f9eb31f6faf47f6190d290c720bbecfc2e8768a7 100644 (file)
@@ -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);
index 608a0ccb11535cd1c745cf90b799798dead30b86..898ebbfe89bcd231d6681f4ce447ab44612f8f3b 100644 (file)
@@ -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);
index 30b8bd9600b378f94c2759bf105b736ae8b0d146..a9f8fa4bbdeca33c47de64763c155150cf42b2ad 100644 (file)
@@ -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);
     }
index 52bb45f1891ac398c75b4fcffdcee90333321d66..b390678854a850a0f35f834aff00672910e30806 100644 (file)
@@ -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);
index c5292575c22f2337b87eab70e66d40fc93fdba3b..63643b7bfc7d9313ff7e1d7c3e0d79f22edbf2e9 100644 (file)
@@ -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);
index 62a3cca1e948ba0d582b0260732bb3d55b67967f..e4b11f2a0415680af2c913b1161855d6ce07e755 100644 (file)
@@ -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);
index 99a85e9e49ad4775107f3a72478467661b2970a4..4cc888004c3c2712551d8c69c90eb7bdbad40c2a 100644 (file)
@@ -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);
index 69a7d5f046e30d021900877e37794d07fda4f811..c8f215a2b057049b2c64c9db103616e52625f5c3 100644 (file)
@@ -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);
index bfa679fcf6ee3e656aa3c052d3e5bd8d62a7a210..bdf6ee95a8b3a317d185e7efaf068ad055b4d3d8 100644 (file)
@@ -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);
 }
index 3d93673e1863d89608fa13443c2abe9ad8520f30..caa58ad0f18e61fc4739e4e6e634496fe27dc4b4 100644 (file)
@@ -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().
index 3c64e75fca8a2e131bc5bebfd54df3be44852a9d..efe18adb4a8d100600056f5037abfd50ae40b58f 100644 (file)
@@ -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);
index dedf9e21e9a08960839a6b60100821e5312f1130..c5156d84185ebda73c159b38434e7e9f7aa007f3 100644 (file)
@@ -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);
 
index d6773a264101dcecc4e3855e530cf3c8e3df4961..8fe4c0e0d4af36b47b279db180469acc6272687f 100644 (file)
@@ -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));
index 37faaaf7d193034845535a81fedd36fac29bccf4..d787f29004550be6b15f8b10604676226f2e11a5 100644 (file)
@@ -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))
index 858f0cbaf9ee00b24acf92e06f51650628f6a63e..cfe8bb49f7a3ad1b0516cfd54da90f9e05b0a7c9 100644 (file)
@@ -472,6 +472,7 @@ later:
 #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);
index ca83a0a0806ce130b41470013b28d2f75453bf3e..0de5245585e6f06da5f6eb1c9578c9e9817abe69 100644 (file)
@@ -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);
 }
index 7c5d6eb34cae08fe99bd6e1ad1b7aad2127279a8..5ec627558abbfe6c226ca526489177466b4d0be5 100644 (file)
@@ -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) {