fix(01-03): don't treat SIGTERM as crash, fix async callbacks in crash handler

- Only auto-restart on positive exit codes (genuine crashes), not negative
  return codes (signals like SIGTERM from our own process management)
- Add iscoroutinefunction check for on_error in crash handler max-retry path

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikkel Georgsen 2026-02-04 17:58:27 +00:00
parent d08f3527cd
commit 3cc97adcd0

View file

@ -230,8 +230,10 @@ class ClaudeSubprocess:
returncode = await self._process.wait() returncode = await self._process.wait()
logger.info(f"Claude Code process exited: returncode={returncode}") logger.info(f"Claude Code process exited: returncode={returncode}")
# Handle crash (non-zero exit) # Handle crash (non-zero exit, but not signals from our own termination)
if returncode != 0: # Negative return codes are signals (e.g., -15 = SIGTERM, -9 = SIGKILL)
# Only auto-restart on genuine crashes (positive non-zero exit codes)
if returncode is not None and returncode > 0:
await self._handle_crash() await self._handle_crash()
return return
@ -405,7 +407,10 @@ class ClaudeSubprocess:
error_msg = f"Claude failed to restart after {self.MAX_CRASH_RETRIES} attempts" error_msg = f"Claude failed to restart after {self.MAX_CRASH_RETRIES} attempts"
logger.error(error_msg) logger.error(error_msg)
if self.on_error: if self.on_error:
self.on_error(error_msg) if inspect.iscoroutinefunction(self.on_error):
asyncio.create_task(self.on_error(error_msg))
else:
self.on_error(error_msg)
self._crash_count = 0 # Reset for next session self._crash_count = 0 # Reset for next session
return return