diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index 5e0d5336aa9..b5926815d97 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -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: diff --git a/tests/litellm/proxy/test_prisma_engine_watchdog.py b/tests/litellm/proxy/test_prisma_engine_watchdog.py index 011b8002db2..b8e4a7e1fd5 100644 --- a/tests/litellm/proxy/test_prisma_engine_watchdog.py +++ b/tests/litellm/proxy/test_prisma_engine_watchdog.py @@ -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