https://github.com/python/cpython/commit/26f84b0f69f3e0be6b969939511ffee8d0ff3c95
commit: 26f84b0f69f3e0be6b969939511ffee8d0ff3c95
branch: 3.15
author: Neko Asakura <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-11-06T13:17:05Z
summary:
[3.15] gh-161419: fix weakref reviving a dying object in free-threading
(GH-161431) (#161488)
(cherry picked from commit 85a67bafb4e0dfc9eeef5f75d6c961e4f6231ace)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-11-05-10-19-48.gh-issue-161419.wc4DV0.rst
M Include/internal/pycore_object.h
M Lib/test/test_weakref.py
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index a15685450f54db..d8b93040b2f98f 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -720,6 +720,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
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index ddfc2c395f9a5d..b43a25af32fd85 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -1,4 +1,5 @@
import gc
+import io
import sys
import doctest
import unittest
@@ -1012,6 +1013,29 @@ def cb(wparent):
del root
gc.collect()
+ def test_ref_to_object_dying_after_finalizer(self):
+ cleared = []
+ class Attr:
+ def __del__(self):
+ cleared.append(self.wr() is None)
+
+ class SetWithDel(set):
+ __slots__ = ('a',)
+ def __del__(self):
+ pass
+
+ class Raw(io.RawIOBase):
+ __slots__ = ('a',)
+
+ for cls in (SetWithDel, Raw):
+ with self.subTest(cls=cls.__name__):
+ cleared.clear()
+ o = cls()
+ o.a = Attr()
+ o.a.wr = weakref.ref(o)
+ del o
+ self.assertEqual(cleared, [True])
+
def test_callback_attribute(self):
x = Object(1)
callback = lambda ref: None
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-11-05-10-19-48.gh-issue-161419.wc4DV0.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-11-05-10-19-48.gh-issue-161419.wc4DV0.rst
new file mode 100644
index 00000000000000..0d6605a9eeb550
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-11-05-10-19-48.gh-issue-161419.wc4DV0.rst
@@ -0,0 +1,3 @@
+Fix a crash in the :term:`free-threaded build` where a weak reference could
+revive an object whose finalizer had already run during deallocation, causing
+it to be deallocated twice.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]