fix(proxy): Windows compatibility for Prisma engine watchdog

Guard os.waitpid and os.WNOHANG usage with sys.platform check.
These APIs are Unix-only; on Windows they cause AttributeError
and prevent proxy startup.

- _try_waitpid_watch: return False on Windows, fall back to
  os.kill polling
- _reap_all_zombies: return empty set on Windows (no zombies)

Add unit tests for Windows path.

Made-with: Cursor
This commit is contained in:
shivam 2026-03-12 15:49:55 -07:00
parent 97947c2542
commit d1bd3dec87
2 changed files with 25 additions and 1 deletions

View file

@ -4,6 +4,7 @@ import hashlib
import json
import os
import smtplib
import sys
import threading
import time
import traceback
@ -3603,7 +3604,11 @@ class PrismaClient:
Returns a set of reaped PIDs. As PID 1 in Docker (or any
process that spawns children), we must reap ALL terminated
children to prevent zombie accumulation.
No-op on Windows: os.waitpid and os.WNOHANG are Unix-only.
"""
if sys.platform == "win32":
return set()
reaped: set = set()
while True:
try:
@ -3624,7 +3629,11 @@ class PrismaClient:
via call_soon_threadsafe.
Returns True if the thread was started, False on failure.
On Windows, returns False immediately (os.waitpid/WNOHANG are Unix-only);
caller falls back to os.kill polling.
"""
if sys.platform == "win32":
return False
try:
probe_pid, _ = os.waitpid(pid, os.WNOHANG)
except ChildProcessError:

View file

@ -342,10 +342,25 @@ async def test_stop_watchdog_task_also_stops_engine_watcher(
# ---------------------------------------------------------------------------
# waitpid thread (cross-platform)
# waitpid thread (Unix only; Windows falls back to os.kill polling)
# ---------------------------------------------------------------------------
def test_try_waitpid_watch_returns_false_on_windows(engine_client):
"""_try_waitpid_watch returns False on Windows (os.waitpid/WNOHANG unavailable)."""
with patch("sys.platform", "win32"):
result = engine_client._try_waitpid_watch(1234)
assert result is False
assert engine_client._engine_wait_thread is None
def test_reap_all_zombies_returns_empty_on_windows(engine_client):
"""_reap_all_zombies returns empty set on Windows (waitpid unavailable)."""
with patch("sys.platform", "win32"):
reaped = PrismaClient._reap_all_zombies()
assert reaped == set()
def test_try_waitpid_watch_returns_false_when_not_child(engine_client):
"""_try_waitpid_watch returns False when PID is not our child process."""
engine_client._engine_pid = 9999