From bda0c099ab5caf99686a32c89942fed4f3d11a94 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 7 Jul 2026 16:30:09 +0000 Subject: [PATCH] fix(shell): guard _reap_pid on os.waitpid availability Windows CI runs Unix-path unit tests by patching _IS_WINDOWS=False while still on win32, where os.WNOHANG/os.waitpid do not exist. Use capability checks so reaping is a no-op on platforms without waitpid rather than trusting the (mockable) platform flag. --- nanobot/agent/tools/shell.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/nanobot/agent/tools/shell.py b/nanobot/agent/tools/shell.py index 81f0f2c4..539b68c1 100644 --- a/nanobot/agent/tools/shell.py +++ b/nanobot/agent/tools/shell.py @@ -47,11 +47,17 @@ def _reap_pid(pid: int) -> None: Call this after killing or after normal completion of any subprocess as a safety net — asyncio's child-watcher *should* have reaped it, but in containers / edge-cases it sometimes doesn't. + + Uses ``os`` capability checks rather than ``_IS_WINDOWS`` so this is + safe when tests patch the platform flag while still running on Windows + (``os.waitpid`` / ``os.WNOHANG`` do not exist there). """ - if _IS_WINDOWS: + waitpid = getattr(os, "waitpid", None) + wnohang = getattr(os, "WNOHANG", None) + if waitpid is None or wnohang is None: return try: - os.waitpid(pid, os.WNOHANG) + waitpid(pid, wnohang) except (ProcessLookupError, ChildProcessError): # Already reaped, or not our child — both are fine. pass