Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions litellm/proxy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import json
import os
import smtplib
import sys
import threading
import time
import traceback
Expand Down Expand Up @@ -3663,7 +3664,11 @@ def _reap_all_zombies() -> set:
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:
Expand All @@ -3684,7 +3689,11 @@ def _try_waitpid_watch(self, pid: int) -> bool:
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:
Expand Down
17 changes: 16 additions & 1 deletion tests/litellm/proxy/test_prisma_engine_watchdog.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading