Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a crash in the free threading build when the GC runs concurrently with a new thread starting.
18 changes: 12 additions & 6 deletions Python/gc_free_threading.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,18 +420,24 @@ merge_queued_objects(_PyThreadStateImpl *tstate, struct collection_state *state)
static void
process_delayed_frees(PyInterpreterState *interp)
{
// In STW status, we can observe the latest write sequence by
// advancing the write sequence immediately.
// While we are in a "stop the world" pause, we can observe the latest
// write sequence by advancing the write sequence immediately.
_Py_qsbr_advance(&interp->qsbr);
_PyThreadStateImpl *current_tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
_Py_qsbr_quiescent_state(current_tstate->qsbr);

// Merge the queues from other threads into our own queue so that we can
// process all of the pending delayed free requests at once.
HEAD_LOCK(&_PyRuntime);
PyThreadState *tstate = interp->threads.head;
while (tstate != NULL) {
_PyMem_ProcessDelayed(tstate);
tstate = (PyThreadState *)tstate->next;
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
_PyThreadStateImpl *other = (_PyThreadStateImpl *)p;
if (other != current_tstate) {
llist_concat(&current_tstate->mem_free_queue, &other->mem_free_queue);
}
}
HEAD_UNLOCK(&_PyRuntime);

_PyMem_ProcessDelayed((PyThreadState *)current_tstate);
}

// Subtract an incoming reference from the computed "gc_refs" refcount.
Expand Down
Loading