diff --git a/client/driver/executor/executor.go b/client/driver/executor/executor.go index 5f19cdc72729..53d6aa4bf0a0 100644 --- a/client/driver/executor/executor.go +++ b/client/driver/executor/executor.go @@ -445,6 +445,17 @@ func ClientCleanup(ic *dstructs.IsolationConfig, pid int) error { return clientCleanup(ic, pid) } +// Cleanup any still hanging user processes +func (e *UniversalExecutor) cleanupUserLeftovers(proc *os.Process) error { + // If new process group was created upon command execution + // we can kill the whole process group now to cleanup any leftovers. + if e.cmd.SysProcAttr != nil && e.cmd.SysProcAttr.Setpgid { + return syscall.Kill(-proc.Pid, syscall.SIGKILL) + } else { + return proc.Kill() + } +} + // Exit cleans up the alloc directory, destroys resource container and kills the // user process func (e *UniversalExecutor) Exit() error { @@ -472,7 +483,7 @@ func (e *UniversalExecutor) Exit() error { if err != nil { e.logger.Printf("[ERR] executor: can't find process with pid: %v, err: %v", e.cmd.Process.Pid, err) - } else if err := proc.Kill(); err != nil && err.Error() != finishedErr { + } else if err := e.cleanupUserLeftovers(proc); err != nil && err.Error() != finishedErr { merr.Errors = append(merr.Errors, fmt.Errorf("can't kill process with pid: %v, err: %v", e.cmd.Process.Pid, err)) } diff --git a/client/driver/executor/executor_linux.go b/client/driver/executor/executor_linux.go index 653025a79149..37bcb3bfc048 100644 --- a/client/driver/executor/executor_linux.go +++ b/client/driver/executor/executor_linux.go @@ -330,15 +330,6 @@ func DestroyCgroup(groups *cgroupConfig.Cgroup, cgPaths map[string]string, execu return mErrs.ErrorOrNil() } -// configure new process group for child process -func (e *UniversalExecutor) setNewProcessGroup() error { - if e.cmd.SysProcAttr == nil { - e.cmd.SysProcAttr = &syscall.SysProcAttr{} - } - e.cmd.SysProcAttr.Setpgid = true - return nil -} - // getCgroupManager returns the correct libcontainer cgroup manager. func getCgroupManager(groups *cgroupConfig.Cgroup, paths map[string]string) cgroups.Manager { return &cgroupFs.Manager{Cgroups: groups, Paths: paths} diff --git a/client/driver/executor/executor_unix.go b/client/driver/executor/executor_unix.go index 90efa32e6fa0..cf2fc3f33440 100644 --- a/client/driver/executor/executor_unix.go +++ b/client/driver/executor/executor_unix.go @@ -5,6 +5,7 @@ package executor import ( "fmt" "io" + "syscall" syslog "github.com/RackSec/srslog" @@ -47,3 +48,12 @@ func (e *UniversalExecutor) collectLogs(we io.Writer, wo io.Writer) { } } } + +// configure new process group for child process +func (e *UniversalExecutor) setNewProcessGroup() error { + if e.cmd.SysProcAttr == nil { + e.cmd.SysProcAttr = &syscall.SysProcAttr{} + } + e.cmd.SysProcAttr.Setpgid = true + return nil +} diff --git a/client/driver/raw_exec.go b/client/driver/raw_exec.go index 832d3959774d..ac6d2f88d0d0 100644 --- a/client/driver/raw_exec.go +++ b/client/driver/raw_exec.go @@ -292,7 +292,7 @@ func (h *rawExecHandle) run() { ps, werr := h.executor.Wait() close(h.doneCh) if ps.ExitCode == 0 && werr != nil { - if e := killProcessGroup(h.userPid); e != nil { + if e := killProcess(h.userPid); e != nil { h.logger.Printf("[ERR] driver.raw_exec: error killing user process group: %v", e) } } diff --git a/client/driver/utils.go b/client/driver/utils.go index e35a154c98f8..2f456b3b2650 100644 --- a/client/driver/utils.go +++ b/client/driver/utils.go @@ -8,7 +8,6 @@ import ( "os/exec" "path/filepath" "strings" - "syscall" "time" "github.com/hashicorp/go-multierror" @@ -110,15 +109,6 @@ func killProcess(pid int) error { return proc.Kill() } -// killProcessGroup kills a process group with the given pid -func killProcessGroup(pid int) error { - proc, err := os.FindProcess(pid) - if err != nil { - return err - } - return syscall.Kill(-proc.Pid, syscall.SIGKILL) -} - // destroyPlugin kills the plugin with the given pid and also kills the user // process func destroyPlugin(pluginPid int, userPid int) error {