summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-06-01 14:26:12 (GMT)
committerGitHub <noreply@github.com>2024-06-01 14:26:12 (GMT)
commit48f3378d6c620e99f17679ee11982a57640d3bb4 (patch)
tree3da6204474060816bb97e1efb16169d86ec501fc /Python
parenta0559849ac2de604ffa410268be262a8482ad23c (diff)
downloadcpython-48f3378d6c620e99f17679ee11982a57640d3bb4.zip
cpython-48f3378d6c620e99f17679ee11982a57640d3bb4.tar.gz
cpython-48f3378d6c620e99f17679ee11982a57640d3bb4.tar.bz2
[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 60593b2052ca275559c11028d50e19f8e5dfee13) Co-authored-by: Sam Gross <colesbury@gmail.com>
Diffstat (limited to 'Python')
-rw-r--r--Python/gc_free_threading.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index ee006bb..e6bd012 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);
}