fix: 修正合成超时分支遗漏杀死已 spawn 播放器导致的残留泄漏
真机用 kill -STOP 验证完 v9.0.2 的看门狗修复后,拿同样的批量测试 场景复测,发现 aplay 残留还在发生:25 个存活进程,10 秒内还在 25→27 继续增长,且意外出现了第二个以 root 身份启动的 pulseaudio 实例(可能是前几轮调试过程中触发的系统自动拉起,已清理,和这次 代码修复无直接关系)。 排查后发现 v9.0.2 的修复漏了一条泄漏路径:speakWithVits 里"合成 卡死"分支(60 秒没有新分段到达)只杀了 vitsWorker,从没杀过已经 spawn 出来、stdin 还开着干等数据的 currentPlayer——这个 aplay 会 永远卡在等一个再也不会来的 EOF,跟 PLAYER_EXIT_TIMEOUT_MS 要解决 的是同一类问题,只是触发路径不同,上一版没覆盖到。 修复:不再满足于在每个 done() 调用点各自记得去杀 currentPlayer, 而是在 cleanup() 这个所有路径共用的收尾出口统一兜底——无论从哪条 分支走到这里,都先用 killWithEscalation() 尝试杀掉还活着的 currentProcess/currentPlayer,再清空引用。正常退出路径下进程已经 退出,再次 kill() 是安全的 no-op,不影响现有行为。 验证:清理现场后用同样的批量测试场景(12 道题连续生成+播报)跑 3 分钟、每 10 秒采样一次 aplay 存活数,全程稳定在 0~1,没有任何 堆积趋势(对比修复前 10 秒内 25→27 的失控状态)。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QeoAy5KmkHuKWHAktpEsaN
This commit is contained in:
parent
95ee66e836
commit
0d2164e1af
@ -1190,7 +1190,23 @@ function speakWithPiper(
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 每轮播报结束时统一调用。之前只是把 currentProcess/currentPlayer 引用置空,
|
||||
* 没有保证对应的系统进程真的退出——真机复测时发现合成卡死分支(见上面
|
||||
* "synth timeout" 处)只杀了 vitsWorker,没杀已经 spawn 出来、stdin 还开着
|
||||
* 干等数据的 aplay,这个进程会永远卡在那等一个再也不会来的 EOF,形成和
|
||||
* PLAYER_EXIT_TIMEOUT_MS 要解决的问题同一性质的泄漏,只是触发路径不同。
|
||||
* 与其在每个 done() 调用点各自记得去杀 currentPlayer,不如在 cleanup()
|
||||
* 这个唯一的收尾出口统一兜底:无论从哪条路径走到这里,都先尝试杀掉还活着
|
||||
* 的进程,再清空引用。
|
||||
*/
|
||||
function cleanup(): void {
|
||||
if (currentProcess) {
|
||||
killWithEscalation(currentProcess)
|
||||
}
|
||||
if (currentPlayer) {
|
||||
killWithEscalation(currentPlayer)
|
||||
}
|
||||
currentProcess = null
|
||||
currentPlayer = null
|
||||
isSpeaking = false
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user