//go:build unix
package runner
import (
"os/exec"
"syscall"
"time"
)
// endOwn kills every process this user may signal, which for anyone
// but root is this user's own, except the caller (kill(2), pid -1).
// None left is success.
func endOwn() error {
if err := syscall.Kill(-1, syscall.SIGKILL); err != nil && err != syscall.ESRCH {
return err
}
return nil
}
// become replaces job-env with the command, under a umask that keeps
// what it writes from everyone outside its group.
func become(path string, argv, env []string) error {
syscall.Umask(0o007)
return syscall.Exec(path, argv, env)
}
// stopTogether puts a command in a process group of its own and, when
// its context ends, kills the whole group: a step's `sleep` or test
// server would otherwise outlive the shell that started it and hold its
// output open, so a stopped task never returned.
func stopTogether(cmd *exec.Cmd) {
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
if cmd.Process == nil {
return nil
}
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
}
cmd.WaitDelay = 5 * time.Second
}