Skip to content

Free-threading: weakref can revive an object being deallocated after its finalizer ran #161419

Open

Description

@eendebakpt

Crash report

On the free-threaded build, a weakref to an object whose deallocation is in progress can
still be dereferenced after tp_finalize has run. Dropping that reference deallocates the
object a second time.

import io, weakref

class Raw(io.RawIOBase):
    __slots__ = ('a',)

class Attr:
    def __del__(self):
        print("weakref deref during dealloc ->", self.wr())

o = Raw()
o.a = Attr()
o.a.wr = weakref.ref(o)
del o

Default build: prints None. Free-threaded build: prints <__main__.Raw object at 0x...>, then hangs or crashes on the second deallocation.

CPython versions tested on:

CPython main branch

Linked PRs

Activity

  1. NekoAsakura commented on Nov 5, 2026

    @NekoAsakura
    Member

    The fast path of _PyObject_ResurrectEnd() sets ob_ref_local to 0 and stops there, so the object is still owned by the current thread. _Py_TryIncrefFast() only checks ownership, and a weakref deref brings it back. The slow path sets ob_tid to 0 and merges the refcount, the fast path should leave the object in the same state.

    --- a/Include/internal/pycore_object.h
    +++ b/Include/internal/pycore_object.h
    @@ -712,6 +712,8 @@ _PyObject_ResurrectEnd(PyObject *op)
         if (_Py_IsOwnedByCurrentThread(op) && local == 1 && shared == 0) {
             // Fast-path: object has a single refcount and is owned by this thread
             _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, 0);
    +        _Py_atomic_store_uintptr_relaxed(&op->ob_tid, _Py_UNOWNED_TID);
    +        _Py_atomic_store_ssize_relaxed(&op->ob_ref_shared, _Py_REF_MERGED);
     # ifdef Py_TRACE_REFS
             _Py_ForgetReference(op);
     # endif
  2. eendebakpt commented on Nov 5, 2026

    @eendebakpt
    ContributorAuthor

    @NekoAsakura Would you like to make a PR?

  3. colesbury commented on Nov 5, 2026

    @colesbury
    Contributor

    The proposed fix looks right to me

  4. added 2 commits that reference this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)topic-free-threadingtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions