Skip to content

Commit 48f3378

Browse files
[3.13] gh-117657: Fix TSAN race in free-threaded GC (GH-119883) (#119903)
Only call `gc_restore_tid()` from stop-the-world contexts. `worklist_pop()` can be called while other threads are running, so use a relaxed atomic to modify `ob_tid`. (cherry picked from commit 60593b2) Co-authored-by: Sam Gross <[email protected]>
1 parent a055984 commit 48f3378

File tree

2 files changed

+2
-6
lines changed

2 files changed

+2
-6
lines changed

Python/gc_free_threading.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ worklist_pop(struct worklist *worklist)
8686
PyObject *op = (PyObject *)worklist->head;
8787
if (op != NULL) {
8888
worklist->head = op->ob_tid;
89-
op->ob_tid = 0;
89+
_Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
9090
}
9191
return op;
9292
}
@@ -189,6 +189,7 @@ merge_refcount(PyObject *op, Py_ssize_t extra)
189189
static void
190190
gc_restore_tid(PyObject *op)
191191
{
192+
assert(_PyInterpreterState_GET()->stoptheworld.world_stopped);
192193
mi_segment_t *segment = _mi_ptr_segment(op);
193194
if (_Py_REF_IS_MERGED(op->ob_ref_shared)) {
194195
op->ob_tid = 0;
@@ -676,7 +677,6 @@ call_weakref_callbacks(struct collection_state *state)
676677
Py_DECREF(temp);
677678
}
678679

679-
gc_restore_tid(op);
680680
Py_DECREF(op); // drop worklist reference
681681
}
682682
}
@@ -986,7 +986,6 @@ cleanup_worklist(struct worklist *worklist)
986986
{
987987
PyObject *op;
988988
while ((op = worklist_pop(worklist)) != NULL) {
989-
gc_restore_tid(op);
990989
gc_clear_unreachable(op);
991990
Py_DECREF(op);
992991
}

Tools/tsan/suppressions_free_threading.txt

-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ race_top:_PyImport_ReleaseLock
3737
race_top:_PyParkingLot_Park
3838
race_top:_PyType_HasFeature
3939
race_top:assign_version_tag
40-
race_top:gc_restore_tid
4140
race_top:insertdict
4241
race_top:lookup_tp_dict
4342
race_top:mi_heap_visit_pages
@@ -65,7 +64,6 @@ race_top:list_get_item_ref
6564
race_top:make_pending_calls
6665
race_top:set_add_entry
6766
race_top:should_intern_string
68-
race_top:worklist_pop
6967
race_top:_PyEval_IsGILEnabled
7068
race_top:llist_insert_tail
7169
race_top:_Py_slot_tp_getattr_hook
@@ -87,7 +85,6 @@ race_top:sock_close
8785
race_top:tstate_delete_common
8886
race_top:tstate_is_freed
8987
race_top:type_modified_unlocked
90-
race_top:update_refs
9188
race_top:write_thread_id
9289
race_top:PyThreadState_Clear
9390

0 commit comments

Comments
 (0)