]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117657: Fix TSAN race in free-threaded GC (#119883)
authorSam Gross <colesbury@gmail.com>
Sat, 1 Jun 2024 14:04:05 +0000 (10:04 -0400)
committerGitHub <noreply@github.com>
Sat, 1 Jun 2024 14:04:05 +0000 (10:04 -0400)
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`.

Python/gc_free_threading.c
Tools/tsan/suppressions_free_threading.txt

index ee006bb4aa12b78a41a81adab8bd234bd1e19723..e6bd012c40ee82a3720f301eca4f14a60c39d65b 100644 (file)
@@ -86,7 +86,7 @@ worklist_pop(struct worklist *worklist)
     PyObject *op = (PyObject *)worklist->head;
     if (op != NULL) {
         worklist->head = op->ob_tid;
-        op->ob_tid = 0;
+        _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
     }
     return op;
 }
@@ -189,6 +189,7 @@ merge_refcount(PyObject *op, Py_ssize_t extra)
 static void
 gc_restore_tid(PyObject *op)
 {
+    assert(_PyInterpreterState_GET()->stoptheworld.world_stopped);
     mi_segment_t *segment = _mi_ptr_segment(op);
     if (_Py_REF_IS_MERGED(op->ob_ref_shared)) {
         op->ob_tid = 0;
@@ -676,7 +677,6 @@ call_weakref_callbacks(struct collection_state *state)
             Py_DECREF(temp);
         }
 
-        gc_restore_tid(op);
         Py_DECREF(op);  // drop worklist reference
     }
 }
@@ -986,7 +986,6 @@ cleanup_worklist(struct worklist *worklist)
 {
     PyObject *op;
     while ((op = worklist_pop(worklist)) != NULL) {
-        gc_restore_tid(op);
         gc_clear_unreachable(op);
         Py_DECREF(op);
     }
index cda57d78067bb32da615c37332b57058bba5765b..951635e7c6533dacd66cd9fef324e956ea4f3030 100644 (file)
@@ -37,7 +37,6 @@ race_top:_PyImport_ReleaseLock
 race_top:_PyParkingLot_Park
 race_top:_PyType_HasFeature
 race_top:assign_version_tag
-race_top:gc_restore_tid
 race_top:insertdict
 race_top:lookup_tp_dict
 race_top:mi_heap_visit_pages
@@ -64,7 +63,6 @@ race_top:list_get_item_ref
 race_top:make_pending_calls
 race_top:set_add_entry
 race_top:should_intern_string
-race_top:worklist_pop
 race_top:_PyEval_IsGILEnabled
 race_top:llist_insert_tail
 race_top:_Py_slot_tp_getattr_hook
@@ -86,7 +84,6 @@ race_top:sock_close
 race_top:tstate_delete_common
 race_top:tstate_is_freed
 race_top:type_modified_unlocked
-race_top:update_refs
 race_top:write_thread_id
 race_top:PyThreadState_Clear