summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-06-04 13:42:13 (GMT)
committerGitHub <noreply@github.com>2024-06-04 13:42:13 (GMT)
commite69d068ad0bd6a25434ea476a647b635da4d82bb (patch)
tree516b36fa60e740c6ffb7a38bcc73b423783477c3 /Python
parentbd8c1f97e1709b5e8b07c31b1bc7b73acc76169d (diff)
downloadcpython-e69d068ad0bd6a25434ea476a647b635da4d82bb.zip
cpython-e69d068ad0bd6a25434ea476a647b635da4d82bb.tar.gz
cpython-e69d068ad0bd6a25434ea476a647b635da4d82bb.tar.bz2
gh-117657: Fix race involving GC and heap initialization (#119923)
The `_PyThreadState_Bind()` function is called before the first `PyEval_AcquireThread()` so it's not synchronized with the stop the world GC. We had a race where `gc_visit_heaps()` might visit a thread's heap while it's being initialized. Use a simple atomic int to avoid visiting heaps for threads that are not yet fully initialized (i.e., before `tstate_mimalloc_bind()` is called). The race was reproducible by running: `python Lib/test/test_importlib/partial/pool_in_threads.py`.
Diffstat (limited to 'Python')
-rw-r--r--Python/gc_free_threading.c4
-rw-r--r--Python/pystate.c2
2 files changed, 6 insertions, 0 deletions
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index d005b79..f19362c 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -252,6 +252,10 @@ gc_visit_heaps_lock_held(PyInterpreterState *interp, mi_block_visit_fun *visitor
// visit each thread's heaps for GC objects
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
struct _mimalloc_thread_state *m = &((_PyThreadStateImpl *)p)->mimalloc;
+ if (!_Py_atomic_load_int(&m->initialized)) {
+ // The thread may not have called tstate_mimalloc_bind() yet.
+ continue;
+ }
arg->offset = offset_base;
if (!mi_heap_visit_blocks(&m->heaps[_Py_MIMALLOC_HEAP_GC], true,
diff --git a/Python/pystate.c b/Python/pystate.c
index d029391..e1a9590 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -3074,6 +3074,8 @@ tstate_mimalloc_bind(PyThreadState *tstate)
// _PyObject_GC_New() and similar functions temporarily override this to
// use one of the GC heaps.
mts->current_object_heap = &mts->heaps[_Py_MIMALLOC_HEAP_OBJECT];
+
+ _Py_atomic_store_int(&mts->initialized, 1);
#endif
}