Summary
A normal systemctl stop on a healthy engine leaves the unit in failed:
août 03 10:07:38 systemd[1]: Stopping colibri.service...
août 03 10:07:49 systemd[1]: colibri.service: Main process exited, code=exited, status=1/FAILURE
août 03 10:07:49 systemd[1]: colibri.service: Failed with result 'exit-code'.
août 03 10:07:49 systemd[1]: Stopped colibri.service.
Nothing went wrong. The engine had served for 2 h 50 min, systemd sent SIGTERM, and the process exited 1. systemd correctly records that as a failure.
Consequences
systemctl is-failed is useless as a health check. After any planned stop the unit reports failed, so the state cannot distinguish "was stopped on purpose" from "crashed". On a box where the engine is stopped and started routinely — benchmarking, model swaps, maintenance — the unit is in failed most of the time it is not running.
Every start needs reset-failed first. With StartLimitBurst set, a few stop/start cycles trip the rate limiter and the unit refuses to start at all until manually reset. Every automation script I wrote against this engine ends up carrying:
systemctl stop colibri
...
systemctl reset-failed colibri # otherwise the next start may be refused
systemctl start colibri
which is a workaround for the exit code, not for anything real.
Two ways to fix it, in preference order
1. Exit 0 on SIGTERM. The engine already has a soft-stop path — colibri.c documents SIGINT closing the current turn "per la stessa via del tetto NGEN (stats, usage_save, KV append, sentinella END tutti normali)", i.e. stats flushed, .coli_usage saved, KV appended. SIGTERM should land in the same place and return 0. That also makes the shutdown correct, not just quiet: a SIGTERM today does not obviously go through usage_save, which on a long-lived serve process is the learned routing profile.
2. Failing that, document SuccessExitStatus=1 in the systemd example. This is a smaller fix and it is honest — it tells systemd that 1 is an expected shutdown code. But it also makes a genuine exit-1 failure invisible, so it is second best.
I would rather send the first as a PR than the second, but SIGTERM handling in a serve loop touches shutdown ordering and I would want to know whether you consider the SIGINT path safe to share before I go near it.
Reproduce
systemctl start colibri # let it load and serve one request
systemctl stop colibri
systemctl is-failed colibri # -> failed
Observed on dev @ 7fb1159, Ubuntu 24.04, CUDA build sm_86, 4× RTX A6000, coli web under systemd. Not GLM-specific as far as I can tell — the exit path is in the serve loop, not the model code.
Summary
A normal
systemctl stopon a healthy engine leaves the unit infailed:Nothing went wrong. The engine had served for 2 h 50 min, systemd sent SIGTERM, and the process exited 1. systemd correctly records that as a failure.
Consequences
systemctl is-failedis useless as a health check. After any planned stop the unit reportsfailed, so the state cannot distinguish "was stopped on purpose" from "crashed". On a box where the engine is stopped and started routinely — benchmarking, model swaps, maintenance — the unit is infailedmost of the time it is not running.Every start needs
reset-failedfirst. WithStartLimitBurstset, a few stop/start cycles trip the rate limiter and the unit refuses to start at all until manually reset. Every automation script I wrote against this engine ends up carrying:systemctl stop colibri ... systemctl reset-failed colibri # otherwise the next start may be refused systemctl start colibriwhich is a workaround for the exit code, not for anything real.
Two ways to fix it, in preference order
1. Exit 0 on SIGTERM. The engine already has a soft-stop path —
colibri.cdocuments SIGINT closing the current turn "per la stessa via del tetto NGEN (stats, usage_save, KV append, sentinella END tutti normali)", i.e. stats flushed,.coli_usagesaved, KV appended. SIGTERM should land in the same place and return 0. That also makes the shutdown correct, not just quiet: a SIGTERM today does not obviously go throughusage_save, which on a long-lived serve process is the learned routing profile.2. Failing that, document
SuccessExitStatus=1in the systemd example. This is a smaller fix and it is honest — it tells systemd that 1 is an expected shutdown code. But it also makes a genuine exit-1 failure invisible, so it is second best.I would rather send the first as a PR than the second, but SIGTERM handling in a serve loop touches shutdown ordering and I would want to know whether you consider the SIGINT path safe to share before I go near it.
Reproduce
Observed on
dev@7fb1159, Ubuntu 24.04, CUDA build sm_86, 4× RTX A6000,coli webunder systemd. Not GLM-specific as far as I can tell — the exit path is in the serve loop, not the model code.