mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-09-30 06:13:14 +00:00
## 现象
线上关停必超时:systemd 报 `State 'stop-sigterm' timed out. Killing.`,
其中只有 bili 报 `[proc] bili SIGKILL 后 2s 仍未被收割`,之后近 90 秒无日志。
## 根因
本插件用 `exec.Command("yt-dlp", ...)` + `cmd.Run()`:
- 无 CommandContext ⇒ Stop 无法取消
- 无 Setpgid ⇒ yt-dlp 与本插件同进程组
- Stop() 是 `return nil` ⇒ 内核 Kill 插件本体时,yt-dlp 变孤儿
yt-dlp 还会再 fork ffmpeg,**孙进程继承本插件的 stdout 管道写端**。
插件被 SIGKILL 后孙进程仍持有写端 ⇒ 内核 readLoop 永远等不到 EOF
⇒ `Kill()` 末尾的 readerWG.Wait 永不返回 ⇒ 整个关停挂死。
## 改法
1. 两处 `exec.Command` → `exec.CommandContext`,Stop 里 cancel 能掐掉
2. `setPgid` 让命令自成进程组:yt-dlp 拉起的 ffmpeg 也在组内,
kill(-pgid) 能一次带走整棵子进程树,不留孤儿
3. `Stop()` 不再是空实现:cancel 之后**必须 wait**。
只 cancel 不 wait 的话内核会先释放共享段,而 yt-dlp 还在写 stdout ——
那正是内核 readLoop 挂死的成因。`runWG` 等它真正退出。
顺带:取消时返回明确文案("已取消(插件停止)")而不是含糊的 exec 错误。
内核侧的三处修法(Setpgid / 杀进程组 / readerWG 超时)在主仓 ceeef0b,
对所有 8 个同样 exec.Command 且无进程组隔离的插件都有效。
验证:hmapdev build 通过;主仓部署后实测关停 90s → 1s、
`[homed] stopped` 打出、孙进程无残留。