Misc. bug: llama-server –sleep-idle-seconds: a request that arrives as the server falls asleep is never processed

该问题通常发生在 llama-server 启用 --sleep-idle-seconds 后,客户端请求恰好落在服务进入休眠的临界窗口:任务已入队但主循环仍在等待休眠条件,请求被挂起不处理;同一窗口还可能因休眠回调卸载模型而触发 SIGSEGV。优先排查服务是否已进入 sleeping 状态、请求

快速结论:该问题通常发生在 llama-server 启用 --sleep-idle-seconds 后,客户端请求恰好落在服务进入休眠的临界窗口:任务已入队但主循环仍在等待休眠条件,请求被挂起不处理;同一窗口还可能因休眠回调卸载模型而触发 SIGSEGV。优先排查服务是否已进入 sleeping 状态、请求是否在 wait_until_no_sleep() 与 post() 之间到达。

适用环境:llama.cpp llama-server;Issue 已确认的环境包括 Windows x86_64(Clang 20.1.8,版本 0.5.0-dev build 11160,commit 70c4e1582)与 Linux(b11368 release binary,ubuntu-x64,CPU only,模型 gemma-3-1b-it-Q4_K_M,参数 -np 1 -c 512 --sleep-idle-seconds 1)。Issue 指出 tools/server/server-queue.cpp 在当前 master 与 v0.5.0 中未改动,逻辑与平台无关。

最快修复方案:暂无确认的一步修复方案。Issue 中讨论的修复方向为“在处理请求期间阻止进入休眠”,即在 mutex_tasks 下维护在途请求计数并让 should_sleep() 检查该计数;可优先尝试该方向,但它属于提案而非已验证的合并修复。

注意事项:Issue 评论指出,仅靠 !queue_tasks.empty() 唤醒只能修复挂起,无法修复崩溃,因为崩溃发生时任务尚未入队;Issue 本身也已 stale 关闭,相关补丁未必已合入你所使用的版本。客户端侧绕行方案属于规避手段,并非服务端修复。

问题场景

用户在运行 llama-server 并启用 --sleep-idle-seconds 时,客户端在服务启动后立即发起 /health → /props → /tokenize → POST /completion。其中 /tokenize 不会重置空闲计时器,因此 completion 请求可能在约 1 秒空闲计时器到期、服务刚进入休眠的瞬间到达。Issue 报告约 8 次运行中有 1 次出现;评论中的 Linux 复现进一步分出两类结果:请求无响应(后续第二个请求才把服务唤醒并补答)以及服务进程 SIGSEGV 崩溃。

崩溃发生在休眠回调卸载模型的同时,路由处理线程仍在进行分词。gdb 栈显示 tokenize_input_prompts → common_tokenize → llama_vocab::impl::tokenize → llm_tokenizer_spm_session::try_add_bigram → llama_vocab::text_to_token。短提示(如两个词)几乎不触发,长提示(17,653 token)在该窗口内更容易崩溃。

报错原文

Misc. bug: llama-server --sleep-idle-seconds: a request that arrives as the server falls asleep is never processed

0.07.454.922 I srv  llama_server: listening on http://127.0.0.1:59267
0.08.462.222 I que    start_loop: entering sleeping state
0.08.462.554 I srv  handle_sleep: server is entering sleeping state
10.08.276.728 W srv          stop: cancel task, id_task = 0

Thread 9 "llama-server" received signal SIGSEGV, Segmentation fault.
#1  llama_vocab::text_to_token(...)
#2  llm_tokenizer_spm_session::try_add_bigram(int, int)
#3  llama_vocab::impl::tokenize(...)
#6  common_tokenize(...)
#9  tokenize_input_prompts(...)
#10 server_routes::handle_completions_impl(...)
#18 httplib::ThreadPool::worker(bool)

原因分析

可能原因(基于 Issue 作者对 server-queue.cpp / server-context.cpp 的阅读):

  • HTTP 线程构造 server_res_generator 时调用 queue_tasks.wait_until_no_sleep()。此时服务仍处于唤醒状态,检查立即通过。
  • 在该线程执行 post() 之前,start_loop() 中的主循环取得 mutex_tasks,发现队列为空且 should_sleep() 为真,于是设置 sleeping = true、执行休眠回调,并在 condition_tasks 上等待 !running || req_stop_sleeping。
  • 随后 post() 将任务入队并调用 condition_tasks.notify_one(),但休眠等待条件不检查 queue_tasks,req_stop_sleeping 也仅由 wait_until_no_sleep() 在发现服务已休眠时设置。因此主循环继续休眠,任务滞留在队列中。
  • 单个客户端不会再发送经过 wait_until_no_sleep() 的请求,所以无法自行唤醒;只有后续请求才会把它唤醒并补答。
  • 崩溃则来自同一窗口的另一后果:休眠回调在路由处理线程已通过屏障、仍在分词时卸载模型,访问已释放状态导致段错误。

环境排查

  • 确认 llama-server 版本:Issue 报告为 0.5.0-dev(build 11160,commit 70c4e1582);Linux 复现为 b11368 release binary。
  • 确认是否使用 --sleep-idle-seconds,以及空闲秒数设置(Issue 复现使用 1)。
  • 确认并发参数:Issue 中 -np 1;评论复现使用 -np 1 -c 512。
  • 确认客户端请求序列是否在启动后紧接着发送,尤其是 /tokenize 后紧跟 POST /completion 的情况。
  • 确认是否出现服务崩溃(查看退出码、signal 11)或仅请求无响应。
  • 确认提示长度:长提示更容易命中崩溃分支。

解决步骤

  1. 先判定症状:若客户端一直等到自身超时且日志只出现 entering sleeping state、没有 exiting sleeping state,属于挂起分支;若连接被关闭且 llama-server 以 signal 11 退出,属于崩溃分支。
  2. 可优先尝试客户端侧绕行方案(评论中验证有效):在发送真实请求前先发送一个极短请求,例如 {"prompt":"hi","n_predict":1},再立即发送真实请求。短请求几乎没有临界窗口,其 post() 会重置 time_last_task,使真实请求获得完整空闲周期。评论称相同 123 次扫描下 123 次全部应答、0 挂起、0 崩溃。
  3. 另一客户端侧绕行:在发送请求前轮询 /props,等待其报告 is_sleeping: true 后再发送。已休眠时请求会走 req_stop_sleeping 路径被正常处理。
  4. 服务端修复方向(可优先尝试,未验证为已合入):在处理请求期间阻止进入休眠,即在 mutex_tasks 下引入在途请求计数,并让 should_sleep() 检查该计数;该方案同时覆盖挂起与崩溃两个窗口。仅修改休眠等待为 !running || req_stop_sleeping || !queue_tasks.empty() 只能修复挂起。
  5. 若无法立即修改服务端或客户端,在空闲敏感场景下先不使用 --sleep-idle-seconds,或把空闲秒数调大到不会与请求时序重叠。

验证方法

启动启用 --sleep-idle-seconds 的服务,在空闲计时器到期边界附近发送请求,观察日志是否出现 exiting sleeping state 或进入正常的 tokenize/processing 流程;客户端是否在自身超时前收到响应。若使用绕行方案,重复多轮边界请求,确认无挂起(无回复且 /props 显示 is_sleeping: true)且服务进程未以 signal 11 退出。评论中的 123 次扫描可作为参考验证强度。

参考来源

ggml-org/llama.cpp #29689

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 34583

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注