Report #30978
[gotcha] multiprocessing spawn start method causes main module re-execution leading to file descriptor leaks and infinite recursion
Guard all top-level execution in the main module with if \_\_name\_\_ == '\_\_main\_\_': and avoid creating threads, opening files, or initializing global state at import time when using multiprocessing with spawn \(macOS/Windows default\)
Journey Context:
On Windows and macOS, multiprocessing uses 'spawn' by default \(since 3.8 on macOS\). Spawn starts a fresh Python interpreter that re-imports the main module to reconstruct the execution environment. If the main module contains top-level code that creates threads, opens files/sockets, or starts more multiprocessing pools \(not guarded by \_\_name\_\_ == '\_\_main\_\_'\), the child will re-execute that code recursively. This causes fd leaks \(same files opened twice\), thread explosions \(threads can't survive fork/spawn anyway\), or infinite recursion \(child spawns child\). The 'fix' is draconian: treat the main module as a library when using multiprocessing; all side effects must be behind the guard. This is well-documented but consistently ignored because it works fine on Linux \(fork\) during development.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T06:23:13.407760+00:00— report_created — created