// Package proc 提供跨平台的"进程组/进程树"终止抽象。一个 Group 把某个进程及其 // 派生的所有子孙进程作为单一单元管理,使 stop/restart/crash 时能整树清理,避免 // dev server(如 pnpm dev → node/vite/esbuild)留下占用端口的孤儿进程。 // // 用法与 *exec.Cmd 生命周期对齐: // // g := proc.NewGroup() // g.Prepare(cmd) // cmd.Start() 之前:Unix 设置 SysProcAttr.Setpgid // cmd.Start() // g.Adopt(cmd) // cmd.Start() 之后:Windows 创建 Job 并 Assign // ... // g.TerminateGroup(done, grace) // 整树优雅终止 // g.Close() // 释放平台句柄 package proc import ( "os/exec" "time" ) // Group 抽象"一个进程及其所有子孙进程"作为单一单元管理。 // 非并发安全:调用方需保证 Prepare/Adopt/TerminateGroup/Close 的串行使用 // (RunSupervisor / ACP Supervisor 已用各自的锁与 done channel 保证)。 type Group interface { // Prepare 在 cmd.Start() 之前设置平台属性(Unix: SysProcAttr.Setpgid)。 Prepare(cmd *exec.Cmd) // Adopt 在 cmd.Start() 之后接管已启动的进程(Windows: 创建 Job 并 // AssignProcessToJobObject)。Unix 为记录 pgid。必须在子进程派生前调用。 Adopt(cmd *exec.Cmd) error // TerminateGroup 优雅终止整组:Unix 先 SIGTERM(-pgid) 等 grace 再 SIGKILL(-pgid); // Windows CloseHandle(job) 触发 KILL_ON_JOB_CLOSE 整树终止。 // done 由调用方(monitor goroutine)关闭,用于感知优雅退出、提前返回。 TerminateGroup(done <-chan struct{}, grace time.Duration) // Close 释放平台句柄(Windows: 关闭 Job handle;Unix: no-op)。幂等。 Close() } // NewGroup 按编译期 build tag 返回 unixGroup / windowsGroup。 func NewGroup() Group { return newGroup() }