diff options
author | Sam Gross <colesbury@gmail.com> | 2024-06-01 10:04:05 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-01 10:04:05 -0400 |
commit | 60593b2052ca275559c11028d50e19f8e5dfee13 (patch) | |
tree | 48fb7cb6ade84098a9d7d91dfdd63ce02ee645c4 /Python/gc_free_threading.c | |
parent | 5152120ae746516670c77e7feed5c4a8912f2bbb (diff) | |
download | cpython-60593b2052ca275559c11028d50e19f8e5dfee13.tar.gz cpython-60593b2052ca275559c11028d50e19f8e5dfee13.zip |
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`.
Diffstat (limited to 'Python/gc_free_threading.c')
-rw-r--r-- | Python/gc_free_threading.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index ee006bb4aa1..e6bd012c40e 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -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); } |