Skip to content

[Bug]: the engine exits 1 on SIGTERM, so every clean systemctl stop leaves the unit failed #810

Description

@ThefloorMiner

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugDifetto verificato nel codice

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions