diff --git a/client/driver/executor/executor.go b/client/driver/executor/executor.go index a3073e1eee5a..5f19cdc72729 100644 --- a/client/driver/executor/executor.go +++ b/client/driver/executor/executor.go @@ -224,6 +224,11 @@ func (e *UniversalExecutor) LaunchCmd(command *ExecCommand) (*ProcessState, erro // set the task dir as the working directory for the command e.cmd.Dir = e.ctx.TaskDir + // start command in separate process group + if err := e.setNewProcessGroup(); err != nil { + return nil, err + } + // configuring the chroot, resource container, and start the plugin // process in the chroot. if err := e.configureIsolation(); err != nil { diff --git a/client/driver/executor/executor_basic.go b/client/driver/executor/executor_basic.go index 123ed47032e2..65030d45b44d 100644 --- a/client/driver/executor/executor_basic.go +++ b/client/driver/executor/executor_basic.go @@ -29,6 +29,10 @@ func (e *UniversalExecutor) configureIsolation() error { return nil } +func (e *UniversalExecutor) setNewProcessGroup() error { + return nil +} + func (e *UniversalExecutor) Stats() (*cstructs.TaskResourceUsage, error) { pidStats, err := e.pidStats() if err != nil { diff --git a/client/driver/executor/executor_linux.go b/client/driver/executor/executor_linux.go index 37bcb3bfc048..653025a79149 100644 --- a/client/driver/executor/executor_linux.go +++ b/client/driver/executor/executor_linux.go @@ -330,6 +330,15 @@ 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/raw_exec.go b/client/driver/raw_exec.go index 966a2affb58f..832d3959774d 100644 --- a/client/driver/raw_exec.go +++ b/client/driver/raw_exec.go @@ -292,8 +292,8 @@ func (h *rawExecHandle) run() { ps, werr := h.executor.Wait() close(h.doneCh) if ps.ExitCode == 0 && werr != nil { - if e := killProcess(h.userPid); e != nil { - h.logger.Printf("[ERR] driver.raw_exec: error killing user process: %v", e) + if e := killProcessGroup(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 2f456b3b2650..e35a154c98f8 100644 --- a/client/driver/utils.go +++ b/client/driver/utils.go @@ -8,6 +8,7 @@ import ( "os/exec" "path/filepath" "strings" + "syscall" "time" "github.com/hashicorp/go-multierror" @@ -109,6 +110,15 @@ 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 {