gh-117657: Fix TSAN race in free-threaded GC (#119883)

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`.
This commit is contained in:
Sam Gross 2024-06-01 10:04:05 -04:00 committed by GitHub
parent 5152120ae7
commit 60593b2052
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 2 additions and 6 deletions

View file

@ -86,7 +86,7 @@ worklist_pop(struct worklist *worklist)
PyObject *op = (PyObject *)worklist->head; PyObject *op = (PyObject *)worklist->head;
if (op != NULL) { if (op != NULL) {
worklist->head = op->ob_tid; worklist->head = op->ob_tid;
op->ob_tid = 0; _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
} }
return op; return op;
} }
@ -189,6 +189,7 @@ merge_refcount(PyObject *op, Py_ssize_t extra)
static void static void
gc_restore_tid(PyObject *op) gc_restore_tid(PyObject *op)
{ {
assert(_PyInterpreterState_GET()->stoptheworld.world_stopped);
mi_segment_t *segment = _mi_ptr_segment(op); mi_segment_t *segment = _mi_ptr_segment(op);
if (_Py_REF_IS_MERGED(op->ob_ref_shared)) { if (_Py_REF_IS_MERGED(op->ob_ref_shared)) {
op->ob_tid = 0; op->ob_tid = 0;
@ -676,7 +677,6 @@ call_weakref_callbacks(struct collection_state *state)
Py_DECREF(temp); Py_DECREF(temp);
} }
gc_restore_tid(op);
Py_DECREF(op); // drop worklist reference Py_DECREF(op); // drop worklist reference
} }
} }
@ -986,7 +986,6 @@ cleanup_worklist(struct worklist *worklist)
{ {
PyObject *op; PyObject *op;
while ((op = worklist_pop(worklist)) != NULL) { while ((op = worklist_pop(worklist)) != NULL) {
gc_restore_tid(op);
gc_clear_unreachable(op); gc_clear_unreachable(op);
Py_DECREF(op); Py_DECREF(op);
} }

View file

@ -37,7 +37,6 @@ race_top:_PyImport_ReleaseLock
race_top:_PyParkingLot_Park race_top:_PyParkingLot_Park
race_top:_PyType_HasFeature race_top:_PyType_HasFeature
race_top:assign_version_tag race_top:assign_version_tag
race_top:gc_restore_tid
race_top:insertdict race_top:insertdict
race_top:lookup_tp_dict race_top:lookup_tp_dict
race_top:mi_heap_visit_pages race_top:mi_heap_visit_pages
@ -64,7 +63,6 @@ race_top:list_get_item_ref
race_top:make_pending_calls race_top:make_pending_calls
race_top:set_add_entry race_top:set_add_entry
race_top:should_intern_string race_top:should_intern_string
race_top:worklist_pop
race_top:_PyEval_IsGILEnabled race_top:_PyEval_IsGILEnabled
race_top:llist_insert_tail race_top:llist_insert_tail
race_top:_Py_slot_tp_getattr_hook race_top:_Py_slot_tp_getattr_hook
@ -86,7 +84,6 @@ race_top:sock_close
race_top:tstate_delete_common race_top:tstate_delete_common
race_top:tstate_is_freed race_top:tstate_is_freed
race_top:type_modified_unlocked race_top:type_modified_unlocked
race_top:update_refs
race_top:write_thread_id race_top:write_thread_id
race_top:PyThreadState_Clear race_top:PyThreadState_Clear