fix: ensure shell processes are properly terminated

This commit is contained in:
Clawdbot 2026-02-16 10:58:30 -08:00
parent 13e4028d42
commit e32e74d20b

View file

@ -10,6 +10,7 @@ import (
"regexp" "regexp"
"runtime" "runtime"
"strings" "strings"
"syscall"
"time" "time"
) )
@ -97,6 +98,7 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]interface{}) *To
cmd = exec.CommandContext(cmdCtx, "powershell", "-NoProfile", "-NonInteractive", "-Command", command) cmd = exec.CommandContext(cmdCtx, "powershell", "-NoProfile", "-NonInteractive", "-Command", command)
} else { } else {
cmd = exec.CommandContext(cmdCtx, "sh", "-c", command) cmd = exec.CommandContext(cmdCtx, "sh", "-c", command)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
} }
if cwd != "" { if cwd != "" {
cmd.Dir = cwd cmd.Dir = cwd
@ -106,7 +108,31 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]interface{}) *To
cmd.Stdout = &stdout cmd.Stdout = &stdout
cmd.Stderr = &stderr cmd.Stderr = &stderr
err := cmd.Run() if err := cmd.Start(); err != nil {
return ErrorResult(fmt.Sprintf("failed to start command: %v", err))
}
done := make(chan error, 1)
go func() { done <- cmd.Wait() }()
var err error
select {
case err = <-done:
case <-cmdCtx.Done():
if cmd.Process != nil {
if runtime.GOOS != "windows" {
if pgid, pgErr := syscall.Getpgid(cmd.Process.Pid); pgErr == nil {
_ = syscall.Kill(-pgid, syscall.SIGKILL)
} else {
_ = cmd.Process.Kill()
}
} else {
_ = cmd.Process.Kill()
}
}
err = <-done
}
output := stdout.String() output := stdout.String()
if stderr.Len() > 0 { if stderr.Len() > 0 {
output += "\nSTDERR:\n" + stderr.String() output += "\nSTDERR:\n" + stderr.String()