1bf5fd08ad
A frozen asyncio loop mid-SIGTERM drain cannot run the drain timeout or status rewrites, so KeepAlive never sees a dead process. Arm an OS-thread watchdog at stop() (drain+60s → faulthandler dump + os._exit) and rewrite state/gateway.heartbeat from a loop task for external liveness checks.