Skip to content

Commit 9f5c4c7

Browse files
[3.14] gh-123619: Fix PyUnstable_Object_EnableDeferredRefcount() (GH-151260) (#151327)
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 435af7f commit 9f5c4c7

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
@@ -144,11 +144,17 @@ class EnableDeferredRefcountingTest(unittest.TestCase):
144144
@support.requires_resource("cpu")
145145
def test_enable_deferred_refcount(self):
146146
from threading import Thread
147+
import gc
147148

148149
self.assertEqual(_testcapi.pyobject_enable_deferred_refcount("not tracked"), 0)
149150
foo = []
150151
self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(foo), int(support.Py_GIL_DISABLED))
151152

153+
# The object must be tracked by the GC
154+
not_gc_tracked = tuple([1, 2])
155+
self.assertFalse(gc.is_tracked(not_gc_tracked))
156+
self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(not_gc_tracked), 0)
157+
152158
# Make sure reference counting works on foo now
153159
self.assertEqual(foo, [])
154160
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
@@ -2728,6 +2728,13 @@ PyUnstable_Object_EnableDeferredRefcount(PyObject *op)
27282728
return 0;
27292729
}
27302730

2731+
if (!PyObject_GC_IsTracked(op)) {
2732+
// When deferred refcount is enabled, the object will only be
2733+
// deallocated by the tracing garbage collector. So it must be tracked
2734+
// by the garbage collector.
2735+
return 0;
2736+
}
2737+
27312738
uint8_t bits = _Py_atomic_load_uint8(&op->ob_gc_bits);
27322739
if ((bits & _PyGC_BITS_DEFERRED) != 0)
27332740
{

0 commit comments

Comments
 (0)