From 6459b8df76b862c68535b150c7c4971eede5d50a Mon Sep 17 00:00:00 2001 From: Shannon Sands Date: Mon, 27 Jul 2026 13:52:11 +1000 Subject: [PATCH] fix(gateway): use no-kill _pid_exists probe in lifecycle ledger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit scripts/check-windows-footguns.py (blocking CI lint) rightly flagged the os.kill(pid, 0) liveness probe: on Windows sig=0 collides with CTRL_C_EVENT and GenerateConsoleCtrlEvent hard-kills the target's whole console group (bpo-14484) — a forensics module must never be able to kill the process it's checking on. Route through gateway.status._pid_exists, the repo's canonical psutil-backed no-kill probe. --- gateway/lifecycle_ledger.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gateway/lifecycle_ledger.py b/gateway/lifecycle_ledger.py index 9dd86e0875e..c76a9edac85 100644 --- a/gateway/lifecycle_ledger.py +++ b/gateway/lifecycle_ledger.py @@ -156,8 +156,14 @@ def _pid_alive_with_start_time(pid: Any, start_time: Any) -> bool: if pid_int <= 0: return False try: - os.kill(pid_int, 0) - except (ProcessLookupError, PermissionError, OSError): + # NOT os.kill(pid, 0): on Windows that sends CTRL_C_EVENT to the + # target's console group (bpo-14484). _pid_exists is the repo's + # canonical no-kill cross-platform probe (psutil-backed). + from gateway.status import _pid_exists + + if not _pid_exists(pid_int): + return False + except Exception: return False if start_time is None: return True # alive; can't disambiguate PID reuse — err on "alive"