Skip to content

Add PyWeakref_IsDead() to test if a weak reference is dead #128008

Closed
@colesbury

Description

@colesbury

Feature or enhancement

// Returns 1 if the pointed to object is dead, 0 if it's alive, and -1 with an error set if `ref` is not a weak reference.
int PyWeakref_IsDead(PyObject *ref);

C API Working Group Issue

Motivation

Prior to Python 3.13, you could check if a weak reference is dead via PyWeakref_GetObject(ref) == Py_None, but that function is now deprecated. You might try writing an "is dead" check using PyWeakref_GetRef. For example:

int is_dead(PyObject *ref) {
    PyObject *tmp;
    if (PyWeakref_GetRef(&ref, &tmp) < 0) {
        return -1;
    }
    else if (tmp == NULL) {
        return 1;
    }
    Py_DECREF(tmp);
    return 0;
}

In addition to not being ergonomic, the problem with this code is that the Py_DECREF(tmp) may introduce a side effect from a calling a destructor, at least in the free threading build where some other thread may concurrently drop the last reference. Our internal _PyWeakref_IS_DEAD implementation avoids this problem, but it's not possible to reimplement that code using our existing public APIs.

This can be a problem when you need to check if a weak reference is dead within a lock, such as when cleaning up dictionaries or lists of weak references -- you don't want to execute arbitrary code via a destructor while holding the lock.

I've run into this in two C API extensions this week that are not currently thread-safe with free threading:

  • CFFI uses a dictionary that maps a string keys to unowned references. I'm working on update it to use PyWeakReference, but the "is dead" clean-up checks are more difficult due to the above issues.
  • Pandas cleans up a list of weak references. (The code is not currently thread-safe, and probably needs a lock.)

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions