https://github.com/python/cpython/commit/dc5ebe3da4defe5d3cda0ca0c781ea20942e8d0f commit: dc5ebe3da4defe5d3cda0ca0c781ea20942e8d0f branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: vstinner <[email protected]> date: 2026-06-11T11:21:26Z summary:
[3.15] gh-123619: Fix PyUnstable_Object_EnableDeferredRefcount() (GH-151260) (#151326) gh-123619: Fix PyUnstable_Object_EnableDeferredRefcount() (GH-151260) Return 0 if the object is not tracked by the GC. (cherry picked from commit 72e7eddce6c7137cef06b6eba15641597919e3d4) Co-authored-by: Victor Stinner <[email protected]> files: A Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst M Lib/test/test_capi/test_object.py M Objects/object.c diff --git a/Lib/test/test_capi/test_object.py b/Lib/test/test_capi/test_object.py index e5c50902a0118d4..433afac875aa7bf 100644 --- a/Lib/test/test_capi/test_object.py +++ b/Lib/test/test_capi/test_object.py @@ -178,11 +178,17 @@ class EnableDeferredRefcountingTest(unittest.TestCase): @support.requires_resource("cpu") def test_enable_deferred_refcount(self): from threading import Thread + import gc self.assertEqual(_testcapi.pyobject_enable_deferred_refcount("not tracked"), 0) foo = [] self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(foo), int(support.Py_GIL_DISABLED)) + # The object must be tracked by the GC + not_gc_tracked = tuple([1, 2]) + self.assertFalse(gc.is_tracked(not_gc_tracked)) + self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(not_gc_tracked), 0) + # Make sure reference counting works on foo now self.assertEqual(foo, []) if support.Py_GIL_DISABLED: diff --git a/Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst b/Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst new file mode 100644 index 000000000000000..4d4c94563330c06 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst @@ -0,0 +1,3 @@ +:c:func:`PyUnstable_Object_EnableDeferredRefcount` now returns ``0`` if the +object is not tracked by the garbage collector: if :func:`gc.is_tracked` is +false. Patch by Victor Stinner. diff --git a/Objects/object.c b/Objects/object.c index e0e26bb50d36537..bd23c2e23881949 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2821,6 +2821,13 @@ PyUnstable_Object_EnableDeferredRefcount(PyObject *op) return 0; } + if (!PyObject_GC_IsTracked(op)) { + // When deferred refcount is enabled, the object will only be + // deallocated by the tracing garbage collector. So it must be tracked + // by the garbage collector. + return 0; + } + uint8_t bits = _Py_atomic_load_uint8(&op->ob_gc_bits); if ((bits & _PyGC_BITS_DEFERRED) != 0) { _______________________________________________ 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]
