You've already forked agentic-coding-workflow
启动项目逻辑
This commit is contained in:
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/yan1h/agent-coding-workflow/internal/audit"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/crypto"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/notify"
|
||||
procgrp "github.com/yan1h/agent-coding-workflow/internal/infra/proc"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/mcp"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/workspace"
|
||||
)
|
||||
@@ -95,6 +96,7 @@ type Process struct {
|
||||
WorktreeID *uuid.UUID // 子 worktree 时填,用于 release
|
||||
|
||||
Cmd *exec.Cmd
|
||||
group procgrp.Group // 进程树句柄(整树终止),Spawn 时 Prepare+Adopt
|
||||
Stdin io.WriteCloser
|
||||
Stdout io.ReadCloser
|
||||
Stderr io.ReadCloser
|
||||
@@ -173,6 +175,11 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
cmd.Dir = sess.CwdPath
|
||||
cmd.Env = osEnv
|
||||
|
||||
// 进程树管理:Prepare 须在 Start 前(Unix Setpgid),Adopt 须在 Start 后
|
||||
// (Windows Job Object)。终止时整树清理,避免 agent 派生的子孙进程残留。
|
||||
group := procgrp.NewGroup()
|
||||
group.Prepare(cmd)
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("stdin pipe: %w", err)
|
||||
@@ -189,6 +196,10 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("start: %w", err)
|
||||
}
|
||||
if err := group.Adopt(cmd); err != nil {
|
||||
_ = cmd.Process.Kill()
|
||||
return nil, fmt.Errorf("adopt process group: %w", err)
|
||||
}
|
||||
|
||||
var decider handlers.PermissionDecider
|
||||
if s.permSvc != nil {
|
||||
@@ -215,6 +226,7 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
UserID: sess.UserID,
|
||||
IsMain: sess.IsMainWorktree,
|
||||
Cmd: cmd,
|
||||
group: group,
|
||||
Stdin: stdin,
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
@@ -307,9 +319,9 @@ func (s *Supervisor) Kill(ctx context.Context, sid uuid.UUID, grace time.Duratio
|
||||
|
||||
proc.KilledByUs.Store(true)
|
||||
|
||||
// 平台差异:Unix 走 SIGTERM + grace + 强 Kill;Windows 直接 Kill。
|
||||
// 实现见 supervisor_unix.go / supervisor_windows.go。
|
||||
s.unixGracefulTerm(proc, grace)
|
||||
// 整树终止:Unix 走 SIGTERM(-pgid) + grace + SIGKILL(-pgid);Windows 关闭
|
||||
// Job 句柄触发 KILL_ON_JOB_CLOSE。实现下沉至 internal/infra/proc。
|
||||
proc.group.TerminateGroup(proc.done, grace)
|
||||
|
||||
select {
|
||||
case <-proc.done:
|
||||
@@ -375,6 +387,10 @@ func (s *Supervisor) monitorProcess(proc *Process) {
|
||||
delete(s.procs, proc.SessionID)
|
||||
s.mu.Unlock()
|
||||
|
||||
// 释放进程树句柄(Windows 关闭 Job handle;Unix no-op)。done 已 close、
|
||||
// 进程已 Wait 返回,此处 Close 不影响 onExit-must-not-relock 不变量。
|
||||
proc.group.Close()
|
||||
|
||||
status := SessionExited
|
||||
if !proc.KilledByUs.Load() {
|
||||
status = SessionCrashed
|
||||
|
||||
Reference in New Issue
Block a user