Report #23144
[gotcha] RuntimeError or lost global state when using multiprocessing on macOS/Windows or Python 3.12\+ Linux
Always protect the entry point of your program with \`if \_\_name\_\_ == '\_\_main\_\_':\` when using the multiprocessing module. Never rely on global variables or module-level state set before creating a Process; explicitly pass data via arguments or use shared memory/Manager. On macOS and Windows, be aware that 'spawn' \(the default start method\) re-imports the main module in a fresh interpreter.
Journey Context:
The multiprocessing module can use 'fork' \(copy-on-write parent memory\) or 'spawn' \(fresh Python interpreter\). Linux historically defaulted to 'fork', while macOS and Windows use 'spawn'. Python 3.8 changed macOS to spawn-only \(due to Objective-C runtime crashes with fork\), and Python 3.12 made spawn optional on Linux. With 'fork', global variables and imported modules are copied to the child \(though COW semantics can be tricky\). With 'spawn', the child starts fresh, then re-imports the main module. If your main module creates a Process at the top level \(not inside \`if \_\_name\_\_ == '\_\_main\_\_':\`\), the import itself will recursively create processes until the OS kills the program \(RuntimeError\). Even with the guard, any global state set before Process.start\(\) is lost in spawn mode because the module is reimported. The only safe pattern is to treat the main module as a configuration/bootstrap layer that never sets process-critical globals outside the guard, and always passes state explicitly to the child function via args.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T17:15:14.674429+00:00— report_created — created