Skip to content

Commit d3ed5d7

Browse files
committed
gh-112529: Don't untrack tuples or dicts with zero refcount
The free-threaded GC sometimes sees objects with zero refcount. This can happen due to the delay in merging biased reference counting fields, and, in the future, due to deferred reference counting. We should not untrack these objects or they will never be collected.
1 parent 8dbfdb2 commit d3ed5d7

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

Python/gc_free_threading.c

+18-15
Original file line numberDiff line numberDiff line change
@@ -374,25 +374,28 @@ update_refs(const mi_heap_t *heap, const mi_heap_area_t *area,
374374
return true;
375375
}
376376

377-
// Untrack tuples and dicts as necessary in this pass.
378-
if (PyTuple_CheckExact(op)) {
379-
_PyTuple_MaybeUntrack(op);
380-
if (!_PyObject_GC_IS_TRACKED(op)) {
381-
gc_restore_refs(op);
382-
return true;
377+
Py_ssize_t refcount = Py_REFCNT(op);
378+
_PyObject_ASSERT(op, refcount >= 0);
379+
380+
if (refcount > 0) {
381+
// Untrack tuples and dicts as necessary in this pass, but not objects
382+
// with zero refcount, which we will want to collect.
383+
if (PyTuple_CheckExact(op)) {
384+
_PyTuple_MaybeUntrack(op);
385+
if (!_PyObject_GC_IS_TRACKED(op)) {
386+
gc_restore_refs(op);
387+
return true;
388+
}
383389
}
384-
}
385-
else if (PyDict_CheckExact(op)) {
386-
_PyDict_MaybeUntrack(op);
387-
if (!_PyObject_GC_IS_TRACKED(op)) {
388-
gc_restore_refs(op);
389-
return true;
390+
else if (PyDict_CheckExact(op)) {
391+
_PyDict_MaybeUntrack(op);
392+
if (!_PyObject_GC_IS_TRACKED(op)) {
393+
gc_restore_refs(op);
394+
return true;
395+
}
390396
}
391397
}
392398

393-
Py_ssize_t refcount = Py_REFCNT(op);
394-
_PyObject_ASSERT(op, refcount >= 0);
395-
396399
// We repurpose ob_tid to compute "gc_refs", the number of external
397400
// references to the object (i.e., from outside the GC heaps). This means
398401
// that ob_tid is no longer a valid thread id until it is restored by

0 commit comments

Comments
 (0)