[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 b1056c2a44)

Co-authored-by: Xuanteng Huang <44627253+xuantengh@users.noreply.github.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Victor Stinner 2025-07-01 11:26:52 +02:00 committed by GitHub
parent 1e3466a1ae
commit e3a277c8d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 75 additions and 73 deletions

View 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)

View file

@ -0,0 +1,2 @@
Fix potential :mod:`weakref` races in an object's destructor on the :term:`free threaded <free
threading>` build.

View 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);

View 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
*/

View 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);

View 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);

View 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);
}

View 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);

View 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);

View 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);
}

View 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);

View 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);

View 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);
}

View 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);

View 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);

View 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);

View 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);
}

View 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);

View 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);

View 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);

View 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);

View 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);

View 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);
}

View 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().

View 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);

View 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);

View 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));

View 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))

View file

@ -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);

View 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);
}

View 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) {