]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/commit
server: fix router mode deadlock on child crash and TOCTOU race in models_max (#20763)
authorBen Racicot <redacted>
Thu, 19 Mar 2026 21:16:05 +0000 (17:16 -0400)
committerGitHub <redacted>
Thu, 19 Mar 2026 21:16:05 +0000 (22:16 +0100)
commitc1b911654a581662c19eb51829705e4ed7020673
tree62fca2e43ebe1a23e2d08dd72a9e0c0e38845c58
parentb739738dadf0b66a59546d7240c554d61c07c2f0
server: fix router mode deadlock on child crash and TOCTOU race in models_max (#20763)

Two bugs in `server_models::load()` that affect router mode reliability:

**Bug 1: Deadlock when child process crashes**

When a child process is killed (e.g., SIGKILL from OS code signature
validation), the monitoring thread deadlocks on `stopping_thread.join()`
because the stopping_thread's wait predicate (`is_stopping`) is never
satisfied — the model name was never inserted into `stopping_models`.
`update_status()` is never reached and the model stays stuck in LOADING
state permanently.

Fix: extend the stopping_thread's wait predicate to also wake when the
child process is no longer alive (`!subprocess_alive()`). When woken by
a dead child, the thread skips the shutdown sequence and returns
immediately. The original `stopping_models.erase()` logic is preserved
for normal unloads.

**Bug 2: TOCTOU race bypasses `--models-max` (ref #20137)**

`unload_lru()` is called outside the mutex, then `load()` acquires the
lock afterward. Under concurrent requests, multiple threads observe
capacity and all proceed to load, exceeding the limit.

Fix: re-check capacity under the lock after `unload_lru()` returns.
If another thread filled the slot in the window between `unload_lru()`
and the lock acquisition, reject with an error instead of silently
exceeding the limit.
tools/server/server-models.cpp