Skip to content

Commit dc5ebe3

Browse files
[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 72e7edd) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 491768d commit dc5ebe3

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

Lib/test/test_capi/test_object.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,17 @@ class EnableDeferredRefcountingTest(unittest.TestCase):
178178
@support.requires_resource("cpu")
179179
def test_enable_deferred_refcount(self):
180180
from threading import Thread
181+
import gc
181182

182183
self.assertEqual(_testcapi.pyobject_enable_deferred_refcount("not tracked"), 0)
183184
foo = []
184185
self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(foo), int(support.Py_GIL_DISABLED))
185186

187+
# The object must be tracked by the GC
188+
not_gc_tracked = tuple([1, 2])
189+
self.assertFalse(gc.is_tracked(not_gc_tracked))
190+
self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(not_gc_tracked), 0)
191+
186192
# Make sure reference counting works on foo now
187193
self.assertEqual(foo, [])
188194
if support.Py_GIL_DISABLED:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:c:func:`PyUnstable_Object_EnableDeferredRefcount` now returns ``0`` if the
2+
object is not tracked by the garbage collector: if :func:`gc.is_tracked` is
3+
false. Patch by Victor Stinner.

Objects/object.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2821,6 +2821,13 @@ PyUnstable_Object_EnableDeferredRefcount(PyObject *op)
28212821
return 0;
28222822
}
28232823

2824+
if (!PyObject_GC_IsTracked(op)) {
2825+
// When deferred refcount is enabled, the object will only be
2826+
// deallocated by the tracing garbage collector. So it must be tracked
2827+
// by the garbage collector.
2828+
return 0;
2829+
}
2830+
28242831
uint8_t bits = _Py_atomic_load_uint8(&op->ob_gc_bits);
28252832
if ((bits & _PyGC_BITS_DEFERRED) != 0)
28262833
{

0 commit comments

Comments
 (0)