2025, Oct 01 19:00
Why Python multiprocessing shows 'Windows fatal exception: access violation' with faulthandler under pytest: the SentinelOne cause and fix
Troubleshooting Python multiprocessing on Windows: faulthandler reveals 'Windows fatal exception: access violation' at process start. SentinelOne caused it.
When a simple multiprocessing script on Windows starts printing “Windows fatal exception: access violation” but keeps running, it’s unsettling. The message appears only when faulthandler is enabled, which is why pytest tends to expose it while a direct Python run might look clean. Below is a minimal case that reproduces the behavior on Windows 10 and Windows 11 with Python 3.10 and 3.12.
Reproducible example
import multiprocessing as mp
import faulthandler
faulthandler.enable()
def worker_task():
    import os
    print(f"Worker PID: {os.getpid()}")
    print("Worker process completed")
def run_case():
    proc = mp.Process(target=worker_task)
    proc.start()
    proc.join()
    print(f"Process exit code: {proc.exitcode}")
if __name__ == "__main__":
    print("Direct run:")
    run_case()
    print("Success")
With faulthandler enabled, the console prints an access violation while the process itself completes and the Python code continues.
What the traceback shows
Windows fatal exception: access violation
Current thread 0x00000f48 (most recent call first):
  File "C:\Python\cpython-3.10.16-windows-x86_64-none\lib\multiprocessing\popen_spawn_win32.py", line 73 in __init__
  File "C:\Python\cpython-3.10.16-windows-x86_64-none\lib\multiprocessing\context.py", line 336 in _Popen
  File "C:\Python\cpython-3.10.16-windows-x86_64-none\lib\multiprocessing\context.py", line 224 in _Popen
  File "C:\Python\cpython-3.10.16-windows-x86_64-none\lib\multiprocessing\process.py", line 121 in start
  File "C:\src\sandbox\minimal.py", line 5 in test_reproduce
This points at child process creation and specifically to _winapi.CreateProcess(). In other words, the message is raised around process startup, not inside your worker code. If faulthandler isn’t enabled, you won’t see this output during a regular Python run; pytest enables faulthandler for you, making the printout visible.
Root cause in this case
The behavior was caused by an antivirus product, SentinelOne agent. Disabling the agent removed the access violation printout; re-enabling brought it back. On another Windows 11 Pro setup with Python 3.12.10 and no antivirus running, the same code runs without the message. As additional sanity checks, using a trivial subprocess and trying a clean Python installation were suggested as ways to isolate whether the issue is tied to multiprocessing or the environment. The minimal example above demonstrates the issue is not dependent on what the child process executes.
Why faulthandler reveals it
faulthandler is designed to surface low-level faults by printing diagnostics to stderr. That’s why pytest users are more likely to notice this message: pytest turns faulthandler on. The script continues executing and completes without a Python exception, but the access violation printout still appears.
Resolution
The resolution here is environmental rather than code-level. Disabling the SentinelOne agent eliminated the access violation printout during process creation, and re-enabling reproduced the message again. No changes to the Python code were required.
Why this matters for Windows, multiprocessing, and pytest users
When working with multiprocessing on Windows, messages originating from process startup can easily be misread as application failures. If you run tests under pytest, faulthandler makes such low-level signals visible even when your code is otherwise functioning. Knowing that an antivirus agent can trigger this printout helps separate false alarms from genuine defects in your worker logic.
Takeaways
If you see “Windows fatal exception: access violation” during mp.Process startup, and your script still completes, consider environmental factors. In the case described above, the SentinelOne agent was the trigger. With faulthandler disabled you may not notice the message at all, whereas pytest surfaces it by default. Verifying on a machine without antivirus, trying a clean Python install, or launching a trivial subprocess are practical ways to confirm the behavior isn’t rooted in your code.
The article is based on a question from StackOverflow by kevinlinxc and an answer by kevinlinxc.