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 ` 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 @@ -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 // 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 // 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 // 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 // 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 // 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 #include // 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 // 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 // offsetof() #include @@ -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 // 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 @@ -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 @@ -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 // 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 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 // 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) {