gc.get_objects
can corrupt in-progress GC in free threading build
#125859
Labels
3.13
bugs and security fixes
3.14
new features, bugs and security fixes
topic-free-threading
type-bug
An unexpected behavior, bug, or error
Bug report
Background
The free threading GC uses two queue-like data structures to keep track of objects:
struct worklist
, which is a singly linked list that repurposesob_tid
for the linked list pointer_PyObjectStack
, which is effectively a dynamically sized array ofPyObject*
. (Implemented using a linked list of fixed size array buffers).The
struct worklist
data structure is convenient because enqueueing objects doesn't require a memory allocation and so can't fail. However, an object can only be part of one "worklist" at a time, because each object has only oneob_tid
field.Bug
Other threads can run while the GC is finalizing cyclic garbage and while it's calling
tp_clear()
and other clean-up.During that time, some thread may call
gc.get_objects()
, which can return otherwise "unreachable" objects. The implementation of_PyGC_GetObjects
temporarily pushes objects to astruct worklist
, including objects that might already be part of some other worklist, overwriting the linked list pointer. This essentially corrupts the state of the in-progress GC and causes assertion failures.Proposed fix
_PyGC_BITS_UNREACHABLE
) from being returned bygc.get_objects()
struct worklist
to the actual GC and use_PyObjectStack
(or some other data structure) in_PyGC_GetObjects()
. This reduces the risk of bugs causing an object to be added to more than one worklist.Linked PRs
gc.get_objects
is called during GC #125882The text was updated successfully, but these errors were encountered: