Prhub

#18582 Add subprocess liveness monitor to detect scheduler crashes

原始 PR 作者 Simon-Li 合并时间 2026-03-29 15:09 文件变更 7 提交数 18 评论 16 代码增减 +300 / -29

执行摘要

添加子进程活跃度监控以检测调度器崩溃,防止僵尸服务状态。

Issue #18421描述了当调度器子进程因NCCL超时等C++级别错误崩溃时,std::terminate()会在Python异常处理前执行,导致主进程无法检测崩溃,形成“僵尸服务”(服务接受请求但无法处理)。PR body明确指出目标是添加监控机制以检测此类崩溃并触发清理,减少故障恢复延迟,引用原文:'When a scheduler subprocess crashes at the C++ level, std::terminate() runs before Python exception handlers, leaving the main process unaware. The service continues accepting requests but cannot process them.'

建议工程师精读python/sglang/srt/utils/watchdog.py中的SubprocessWatchdog类实现,理解其守护线程设计、异常处理和SIGQUIT触发机制;重点关注engine.py的_launch_subprocesses变更,学习如何将监控集成到进程启动流程中,避免跨模块传递;对于信号处理爱好者,tokenizer_manager.py的running_phase_sigquit_handler展示了协调watchdog停止以避免竞态条件的设计决策。

讨论亮点

review讨论由hnyls2002主导,关键交锋包括:

1) 设计简洁性:hnyls2002指出'scheduler_procs should not be kept in the init result as it's only used for watchdog setup',导致重构为返回元组而非扩展SchedulerInitResult(提交0262ae10)。
2) 正确性风险:hnyls2002评论'Why discard the reference of watch dog? When the server receives a SIGQUIT, I think you also need to stop the watch dog.',作者通过提交2bbc0a01修复,确保watchdog引用存储在tokenizer_manager供SIGQUIT处理使用。
3) 测试规范:hnyls2002建议'Register with CustomTestcase',测试文件随后调整注册方式。所有讨论点均被解决,PR最终被批准。

实现拆解

实现方案拆解为四个模块:

1) 监控核心:在watchdog.py中新增SubprocessWatchdog类,使用守护线程每隔1秒轮询子进程is_alive(),检测到异常退出(exitcode != 0)时发送SIGQUIT。
2) 集成层:修改engine.py的_launch_subprocesses和_launch_scheduler_processes方法,返回并存储watchdog实例;更新http_server.py和ray/engine.py以传递watchdog。
3) 信号处理:在tokenizer_manager.py的running_phase_sigquit_handler中添加停止watchdog逻辑,防止正常关闭时误报。
4) 测试验证:新增test_subprocess_watchdog.py,包含6个测试用例覆盖健康进程、崩溃检测、多进程、边缘情况等。

文件 模块 状态 重要度
python/sglang/srt/utils/watchdog.py utils modified 8.0
python/sglang/srt/entrypoints/engine.py entrypoints modified 7.0
python/sglang/srt/managers/tokenizer_manager.py managers modified 6.0
test/registered/unit/utils/test_subprocess_watchdog.py test added 5.0

关键符号

SubprocessWatchdog.__init__ SubprocessWatchdog._monitor_loop Engine._launch_subprocesses running_phase_sigquit_handler

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

watchdog 引用存储与 SIGQUIT 处理 设计

hnyls2002 指出 watchdog 引用在 launch_server() 中被丢弃(使用 _ 占位符),导致 SIGQUIT 处理程序无法访问并停止 watchdog,可能引发误报

结论:作者通过提交 2bbc0a01 修复,将 watchdog 引用存储到 tokenizer_manager._subprocess_watchdog,确保在 running_phase_sigquit_handler 中可调用 stop() · 已解决

scheduler_procs 设计重构 设计

hnyls2002 评论 'scheduler_procs should not be kept in the init result. It is only used in the watch dog building steps.',认为将 scheduler_procs 放入 SchedulerInitResult 会污染数据结构

结论:作者通过提交 0262ae10 重构,将 _launch_scheduler_processes 返回值改为元组 (SchedulerInitResult, scheduler_procs),保持设计简洁 · 已解决

测试注册规范 测试

hnyls2002 在测试文件补丁中评论 'Register with CustomTestcase',提示测试需符合项目规范注册

结论:测试文件后续调整以使用 CustomTestCase 注册,确保 CI 集成正确 · 已解决

风险与影响

技术风险具体包括:

1) 并发风险:watchdog使用守护线程轮询,若is_alive()或exitcode访问抛出异常可能被静默吞没(提交741252f9已修复异常处理)。
2) 误报风险:正常退出(exitcode == 0)可能错误触发SIGQUIT,但代码已显式处理此边缘情况。
3) 兼容性风险:多节点部署中非零rank节点watchdog为None,Ray后端仅监控detokenizer(schedulers为actors),需确保逻辑一致。
4) 性能开销:轮询间隔默认1秒引入轻微CPU开销,但可配置。测试覆盖了关键路径,但生产环境大规模部署需观察稳定性。

影响范围:

1) 用户影响:显著提升系统可靠性,减少因未检测崩溃导致的“僵尸服务”窗口,故障恢复时间从默认20秒健康检查缩短至秒级。
2) 系统影响:添加轻量级监控线程(约每进程1个守护线程),CPU开销可忽略;设计重用现有SIGQUIT清理基础设施,无需改动核心调度逻辑。
3) 团队影响:新增代码需维护,但模块化在watchdog.py中,与现有WatchdogRaw模式一致,降低学习成本;测试用例为后续类似监控功能提供模板。影响程度中等,主要优化错误处理而非功能变更。

守护线程并发 SIGQUIT 误报风险 多节点兼容性

关联 Issue

#18421 [Bug] Scheduler subprocess crash due to NCCL timeout remains undetected, causing zombie service state

完整报告

参与讨论