gh-128008: Add PyWeakref_IsDead() (GH-128009)

The `PyWeakref_IsDead()` function tests if a weak reference is dead
without any side effects. Although you can also detect if a weak
reference is dead using `PyWeakref_GetRef()`, that function returns a
strong reference that must be `Py_DECREF()`'d, which can introduce side
effects if the last reference is concurrently dropped (at least in the
free threading build).
This commit is contained in:
Sam Gross 2024-12-19 10:17:15 -05:00 committed by GitHub
parent b9b3e4a076
commit 7b811d0562
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 41 additions and 0 deletions

View file

@ -3144,6 +3144,7 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
PyObject *ref = UNINITIALIZED_PTR;
assert(PyWeakref_GetRef(weakref, &ref) == 1);
assert(ref == obj);
assert(!PyWeakref_IsDead(weakref));
assert(Py_REFCNT(obj) == (refcnt + 1));
Py_DECREF(ref);
@ -3159,6 +3160,8 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
assert(Py_REFCNT(obj) == 1);
Py_DECREF(obj);
assert(PyWeakref_IsDead(weakref));
// test PyWeakref_GET_OBJECT(), reference is dead
assert(PyWeakref_GET_OBJECT(weakref) == Py_None);
@ -3181,6 +3184,12 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
PyErr_Clear();
assert(ref == NULL);
// test PyWeakRef_IsDead(), invalid type
assert(!PyErr_Occurred());
assert(PyWeakref_IsDead(invalid_weakref) == -1);
assert(PyErr_ExceptionMatches(PyExc_TypeError));
PyErr_Clear();
// test PyWeakref_GetObject(), invalid type
assert(PyWeakref_GetObject(invalid_weakref) == NULL);
assert(PyErr_ExceptionMatches(PyExc_SystemError));
@ -3193,6 +3202,11 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
assert(ref == NULL);
PyErr_Clear();
// test PyWeakref_IsDead(NULL)
assert(PyWeakref_IsDead(NULL) == -1);
assert(PyErr_ExceptionMatches(PyExc_SystemError));
PyErr_Clear();
// test PyWeakref_GetObject(NULL)
assert(PyWeakref_GetObject(NULL) == NULL);
assert(PyErr_ExceptionMatches(PyExc_SystemError));