51 lines
987 B
Go
51 lines
987 B
Go
//go:build linux || darwin
|
|
|
|
package subprocess
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"syscall"
|
|
)
|
|
|
|
type unixProcessTree struct {
|
|
processGroupID int
|
|
}
|
|
|
|
func newOwnedProcessTree() (ownedProcessTree, error) {
|
|
return &unixProcessTree{}, nil
|
|
}
|
|
|
|
func (tree *unixProcessTree) Start(cmd *exec.Cmd) error {
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
if err := cmd.Start(); err != nil {
|
|
return err
|
|
}
|
|
tree.processGroupID = cmd.Process.Pid
|
|
return nil
|
|
}
|
|
|
|
func (tree *unixProcessTree) TerminateGracefully() error {
|
|
return tree.signal(syscall.SIGTERM)
|
|
}
|
|
|
|
func (tree *unixProcessTree) TerminateForcefully() error {
|
|
return tree.signal(syscall.SIGKILL)
|
|
}
|
|
|
|
func (tree *unixProcessTree) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (tree *unixProcessTree) signal(signal syscall.Signal) error {
|
|
if tree.processGroupID <= 0 {
|
|
return nil
|
|
}
|
|
err := syscall.Kill(-tree.processGroupID, signal)
|
|
if errors.Is(err, syscall.ESRCH) || errors.Is(err, os.ErrProcessDone) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|