From 7184a25e44d4562eafa17b71f10b0ea7e978d910 Mon Sep 17 00:00:00 2001 From: James Pine Date: Thu, 16 Apr 2026 01:57:05 -0700 Subject: [PATCH] fix(watchdog): clear stale .keep-running sentinel on startup Follow-up to #402. The sentinel is only removed inside the grace-period "sentinel found" branch. When the HTTP /watchdog/disable request wins the race (normal case on macOS/Linux, occasional on Windows), the _watchdog_disabled=True check returns first and the sentinel is left on disk indefinitely. If a later session spawns a fresh server and the user exits without "keep running", the new watchdog would find that stale sentinel during its grace period and keep the server alive against user intent. Wipe any pre-existing sentinel when the watchdog starts so only signals written during this session's lifetime can influence grace-period decisions. Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/server.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/backend/server.py b/backend/server.py index 2262d4c8..5f8cc0f6 100644 --- a/backend/server.py +++ b/backend/server.py @@ -169,6 +169,19 @@ def _start_parent_watchdog(parent_pid, data_dir=None): if not alive: watchdog_logger.warning(f"Parent PID {parent_pid} not found on first check — disabling watchdog") return + # Clear any stale .keep-running sentinel from a previous session. The + # sentinel is only removed by the watchdog when it's consumed during a + # grace period; if the HTTP /watchdog/disable path wins the race on a + # "keep running" exit, the sentinel is left on disk. Wipe it here so a + # future session can't inherit that stale signal. + if data_dir: + stale = os.path.join(data_dir, ".keep-running") + if os.path.exists(stale): + try: + os.remove(stale) + watchdog_logger.info("Removed stale .keep-running sentinel from previous session") + except OSError as e: + watchdog_logger.warning(f"Failed to remove stale sentinel: {e}") while True: if _watchdog_disabled: watchdog_logger.info("Watchdog disabled (keep server running), stopping monitor")