Report #49419
[gotcha] Deadlock or corrupted state when using multiprocessing 'fork' start method after threading
Explicitly force \`multiprocessing.set\_start\_method\('spawn'\)\` at program entry point if the parent process uses any threads, OR ensure absolutely no locks are held by any thread at the moment of fork \(practically impossible in complex apps\). On POSIX, avoid 'fork' entirely if threading has been initialized.
Journey Context:
On POSIX systems \(Linux, macOS\), multiprocessing defaults to the 'fork' start method for performance reasons. Forking creates a child process by copying the parent's memory space, including the state of all locks \(mutexes, semaphores\) in the C library and Python interpreter. However, fork only copies the calling thread; all other threads vanish. If those vanished threads held locks \(e.g., in the Python memory allocator, logging handlers, or import locks\), those locks remain permanently locked in the child process. When the child attempts to allocate memory or log, it deadlocks immediately. Similarly, file descriptors are shared, causing interleaved writes. The 'spawn' method avoids this by starting a fresh Python interpreter and re-importing modules, ensuring no stale locks or threads exist. The tradeoff is slower startup \(~100ms vs ~1ms\) and the requirement that \`\_\_main\_\_\` be importable. The fix is explicit selection of 'spawn' whenever threading is involved, acknowledging that 'fork' is fundamentally unsafe in multi-threaded programs.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T13:26:11.837145+00:00— report_created — created