[issue42972] [C API] Heap types (PyType_FromSpec) must fully implement the GC protocol

STINNER Victor report at bugs.python.org
Thu May 27 12:58:40 EDT 2021


STINNER Victor <vstinner at python.org> added the comment:

I'm not sure that it's safe to call PyObject_ClearWeakRefs() in tp_clear function. PyObject_ClearWeakRefs() comment starts with:

"This function is called by the tp_dealloc handler to clear weak references."

For example in Modules/arraymodule.c, I don't understand well what assigns weakreflist and what is the object type. Is it a strong reference to a Python object? What is supposed to call Py_DECREF() on it?

Is it enought to call PyObject_ClearWeakRefs() in tp_dealloc?

subtype_dealloc() calls PyObject_ClearWeakRefs(self).

I wrote a short example:
---
import weakref
import ctypes
import sys

class A:
    pass

obj=A()
assert obj.__weakref__ is None

wr1 = weakref.ref(obj)
assert obj.__weakref__ is wr1
print(type(wr1))
print("refcnt(wr1)", sys.getrefcount(wr1))

wr2 = weakref.ref(obj)
assert wr2 is wr1
assert obj.__weakref__ is wr1
print("refcnt(wr1)", sys.getrefcount(wr1))

_PyWeakref_GetWeakrefCount = ctypes.pythonapi._PyWeakref_GetWeakrefCount
_PyWeakref_GetWeakrefCount.argtypes = (ctypes.py_object,)
_PyWeakref_GetWeakrefCount.restype = ctypes.c_size_t
print("_PyWeakref_GetWeakrefCount:", _PyWeakref_GetWeakrefCount(wr1))
---

Output:
---
<class 'weakref'>
refcnt(wr1) 2
refcnt(wr1) 3
_PyWeakref_GetWeakrefCount: 1
---

In this case, wr2 is wr1, __weakreflist__ points to a weakref.ref object instance, and _PyWeakref_GetWeakrefCount() returns 1.

At the first weakref.ref() call, the reference count is 1: "wr1" variable holds this reference. I understand that obj stores a *weak* reference to the Python object "weakref.ref". So it doesn't have to DECREF anything.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue42972>
_______________________________________


More information about the Python-bugs-list mailing list