Files
AutoZero/execx/execx_unix.go
T
Sakurasan d5dac5a6fc feat: AutoZero 通用 Agent 框架(从 AutoGo 五阶段拆分完成)
llm(三协议 Provider)/ session(JSONL 持久化)/ tools(Registry、围栏、
builtin、computer)/ cdp(browser)/ skills / mcp / agent(循环、两级压缩、
编排、审批门控)+ 底座 jsonl/textx/execx/diag/scratch/spill/imagecache。

产品装配代码(config 桥接、schedule 工具、memory/plan/retro/prompt)
留在 AutoGo,宿主接入方式见 MIGRATION.md。
2026-10-26 00:54:46 +08:00

39 lines
1.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build !windows
package execx
import (
"os/exec"
"syscall"
)
// SeparateGroup 让子进程自成进程组(pgid == 子进程 pid),必须在 Start 之前调用。
// 自成组之后 kill(-pgid) 才能把它自己起的孙子一并带走。
//
// 用 Setpgid 而不是 Setsid:本包的工具子进程不需要控制终端,而 setsid 会顺带
// 脱离当前会话,交互性场景(终端里 Ctrl+C)行为会变。常驻 PTY 终端那条路径
// 要的是会话+控制终端,见 webui/terminal_unix.go 的三层回退。
func SeparateGroup(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Setpgid = true
}
// KillTree 杀掉整个进程组。用于自己管生命周期的常驻子进程(MCP stdio server:
// 只 Kill 包装进程会把真正的 server 留成孤儿,还占着 stdout 让读循环永不结束)。
//
// 错误一律吞掉并返回 nil:ESRCH 在这里意味着"进程已经没了",正是我们想要的结果;
// 把它抛给 exec 反而会盖掉真正的失败原因(signal: killed / 退出码),
// 让上层看到的错误信息变成一句无意义的 "no such process"。
func KillTree(cmd *exec.Cmd) error {
if cmd.Process == nil {
return nil
}
pid := cmd.Process.Pid
if err := syscall.Kill(-pid, syscall.SIGKILL); err != nil {
_ = syscall.Kill(pid, syscall.SIGKILL) // 没成组(或组已空):退化为只杀本体
}
return nil
}