Bug Description
(Found by claude, verified by me)
There is a race condition where a thread can begin executing Python code before Py_InitializeEx() has finished importing site.py, resulting in an incomplete Python environment (missing sys.path entries, etc.).
Root Cause
CPython sets runtime->initialized = 1 (which makes Py_IsInitialized() return true) before importing site.py:
// cpython/Python/pylifecycle.c, init_interp_main()
interp->runtime->initialized = 1; // line 1333
if (config->site_import) {
status = init_import_site(); // line 1337 — AFTER initialized=1
PyO3's try_attach() (src/internal/state.rs:83-116) trusts Py_IsInitialized() to mean the interpreter is fully initialized and ready for use. It bypasses the std::sync::Once guard in initialize() (src/interpreter_lifecycle.rs:7-20) that serializes the actual Py_InitializeEx() call.
Race Window
-
Thread A calls Python::attach() → try_attach() sees Py_IsInitialized() == 0 → returns NotInitialized → calls ensure_initialized() → enters call_once_force → calls Py_InitializeEx(0).
-
Inside Py_InitializeEx(0), CPython sets runtime->initialized = 1 (line 1333), then begins importing site.py (line 1337).
-
During the site.py import, the GIL can be temporarily released, particularly if site.py executes for long periods (e.g., many .pth files).
-
Thread B calls Python::attach() → try_attach() checks Py_IsInitialized() at state.rs:98 — it returns 1. Thread B proceeds to do_attach_unchecked() → PyGILState_Ensure() → acquires the GIL while site.py has released it.
-
Thread B is now executing Python code while site.py hasn't finished. sys.path is incomplete, , .pth files are only partially processed, etc.
-
Eventually Thread B releases the GIL, site.py resumes and finishes, Py_InitializeEx(0) returns, and Thread A calls PyEval_SaveThread() — but by then Thread B may have already observed or acted on the incomplete state.
Steps to Reproduce
I haven't written a minimal reproducer yet, I've just observed the symptoms and stared hard (with Claude).
Backtrace
Your operating system and version
n/a
Your Python version (python --version)
n/a
Your Rust version (rustc --version)
n/a
Your PyO3 version
masater
How did you install python? Did you use a virtualenv?
n/a
Additional Info
No response
Bug Description
(Found by claude, verified by me)
There is a race condition where a thread can begin executing Python code before
Py_InitializeEx()has finished importingsite.py, resulting in an incomplete Python environment (missingsys.pathentries, etc.).Root Cause
CPython sets
runtime->initialized = 1(which makesPy_IsInitialized()return true) before importingsite.py:PyO3's
try_attach()(src/internal/state.rs:83-116) trustsPy_IsInitialized()to mean the interpreter is fully initialized and ready for use. It bypasses thestd::sync::Onceguard ininitialize()(src/interpreter_lifecycle.rs:7-20) that serializes the actualPy_InitializeEx()call.Race Window
Thread A calls
Python::attach()→try_attach()seesPy_IsInitialized() == 0→ returnsNotInitialized→ callsensure_initialized()→ enterscall_once_force→ callsPy_InitializeEx(0).Inside
Py_InitializeEx(0), CPython setsruntime->initialized = 1(line 1333), then begins importingsite.py(line 1337).During the
site.pyimport, the GIL can be temporarily released, particularly ifsite.pyexecutes for long periods (e.g., many.pthfiles).Thread B calls
Python::attach()→try_attach()checksPy_IsInitialized()atstate.rs:98— it returns1. Thread B proceeds todo_attach_unchecked()→PyGILState_Ensure()→ acquires the GIL whilesite.pyhas released it.Thread B is now executing Python code while
site.pyhasn't finished.sys.pathis incomplete, ,.pthfiles are only partially processed, etc.Eventually Thread B releases the GIL,
site.pyresumes and finishes,Py_InitializeEx(0)returns, and Thread A callsPyEval_SaveThread()— but by then Thread B may have already observed or acted on the incomplete state.Steps to Reproduce
I haven't written a minimal reproducer yet, I've just observed the symptoms and stared hard (with Claude).
Backtrace
Your operating system and version
n/a
Your Python version (
python --version)n/a
Your Rust version (
rustc --version)n/a
Your PyO3 version
masater
How did you install python? Did you use a virtualenv?
n/a
Additional Info
No response