快速结论:该报错出现在 Langfuse 内置 In-App Agent 沙箱运行时执行长耗时命令并触发 timeoutMs 超时的场景:超时只杀掉 sh 进程本身,后台派生的子进程仍存活。优先排查命令启动方式是否创建了独立进程组,以及超时处理是否向整个进程组发信号。
适用环境:Langfuse 内置 In-App Agent 沙箱运行时(Issue 中涉及的代码路径先后位于 packages/in-app-agent-sandbox-runtime/src/server.ts 与 packages/shared/src/);命令通过 Node.js spawn("sh", ["-lc", command]) 启动。Issue 未提供操作系统、Python、CUDA、显卡或依赖版本信息。
最快修复方案:暂无确认的一步修复方案。Issue 中未记录已合并的修复提交;评论给出的方向是将子进程以 detached: true 启动以获得独立进程组,超时时用 process.kill(-child.pid, "SIGKILL") 向整个进程组发送信号(可优先尝试,但未经验证)。
注意事项:该修复方案来自 Issue 评论的推测性建议,并非已验证提交;修复需落在代码当前实际位置(PR #15421 后运行时代码已迁至 packages/shared/src/),否则可能改错文件。另外需注意沙箱运行时的长期存活特性:在修复上线前,反复超时仍可能累积残留进程。
问题场景
在 Langfuse 内置 In-App Agent 沙箱运行时中,调用方以较短的 timeoutMs 执行命令(Issue 示例为 sleep 300 & wait 配合 timeoutMs: 50)。命令超时后工具返回退出码 124,但沙箱内仍有后台子进程继续运行,持续占用 CPU/内存,甚至在工具已报告失败之后继续修改工作区文件。
报错原文
[bug] Sandbox command timeout leaves descendant processes running
Timeout calls child.kill(SIGKILL) and returns exit code 124.
Only the shell is killed. Background descendants can survive...
原因分析
最可能的原因是命令启动时没有建立独立进程组。Issue 指出 spawn("sh", ["-lc", command], { cwd: WORKSPACE_ROOT }) 既未设置 detached: true,也没有其他进程组/会话设置;超时分支仅对直接子进程调用 child.kill("SIGKILL"),信号只送达 sh 进程,其 fork 出的后代进程不受影响,成为孤儿进程继续运行。由于运行时本身长期存活,这类残留会随重复超时累积。
环境排查
- 确认 Langfuse 版本是否仍包含旧路径
packages/in-app-agent-sandbox-runtime/src/server.ts,或代码已按 PR #15421 迁移到packages/shared/src/,以确定实际需要修改的文件。 - 确认超时处理逻辑中是否存在对子进程的
kill调用,以及是否使用负 PID 向进程组发信号。 - 确认命令启动参数中是否包含
detached: true。 - 复现时记录返回的退出码是否为 124,并核对沙箱内进程列表。
解决步骤
- 在沙箱运行时中找到启动命令的
spawn调用,按当前代码位置(packages/shared/src/)定位,而非旧路径。 - 可优先尝试:为
spawn增加detached: true,使子进程拥有独立进程组。 - 可优先尝试:将超时分支中的
child.kill("SIGKILL")改为process.kill(-child.pid!, "SIGKILL"),向整个进程组发送信号;同时保留返回退出码 124 的现有行为。 - 补充回归测试:使用带后台子进程的命令(如
sleep 300 & wait)配合短超时,断言超时后沙箱内无残留子进程。
验证方法
以 timeoutMs: 50 执行 sleep 300 & wait,确认调用返回退出码 124;随后检查沙箱进程列表,确认没有由该命令派生的后台进程存活。可重复多次超时操作,观察 CPU/内存是否不再累积,并确认工作区没有出现超时后的写入。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![[Bug]: /api/v1/dify/retrieval resets the connection (502 / "Reached max retries") because build_error_result sets HTTP status to RetCode.ARG](https://www.chat-gpts.plus/wp-content/uploads/2026/11/16208-b69fbe48-768x403.jpg)
