diff options
author | Alexander Morozov <lk4d4@docker.com> | 2015-04-10 11:04:30 -0700 |
---|---|---|
committer | Jessica Frazelle <jess@docker.com> | 2015-04-13 12:28:22 -0700 |
commit | 10affa8018f5b49288a83b7ca3096504e279ca63 (patch) | |
tree | 759aeb2be7d07201712ce6168561b474e2840b5d | |
parent | ce27fa2716272e0304aae0461304ea101e0d6312 (diff) | |
download | docker-10affa8018f5b49288a83b7ca3096504e279ca63.tar.gz |
Get process list after PID 1 dead
Fix #11087
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit ac8bd12b39d39a9361adc174bdff7837e771460d)
-rw-r--r-- | daemon/execdriver/native/driver.go | 44 | ||||
-rw-r--r-- | integration-cli/docker_cli_run_test.go | 25 |
2 files changed, 54 insertions, 15 deletions
diff --git a/daemon/execdriver/native/driver.go b/daemon/execdriver/native/driver.go index 353e1da51e..285ac9ed35 100644 --- a/daemon/execdriver/native/driver.go +++ b/daemon/execdriver/native/driver.go @@ -190,6 +190,34 @@ func notifyOnOOM(container libcontainer.Container) <-chan struct{} { return oom } +func killCgroupProcs(c libcontainer.Container) { + var procs []*os.Process + if err := c.Pause(); err != nil { + log.Warn(err) + } + pids, err := c.Processes() + if err != nil { + // don't care about childs if we can't get them, this is mostly because cgroup already deleted + log.Warnf("Failed to get processes from container %s: %v", c.ID(), err) + } + for _, pid := range pids { + if p, err := os.FindProcess(pid); err == nil { + procs = append(procs, p) + if err := p.Kill(); err != nil { + log.Warn(err) + } + } + } + if err := c.Resume(); err != nil { + log.Warn(err) + } + for _, p := range procs { + if _, err := p.Wait(); err != nil { + log.Warn(err) + } + } +} + func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*os.ProcessState, error) { return func() (*os.ProcessState, error) { pid, err := p.Pid() @@ -197,8 +225,6 @@ func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*o return nil, err } - processes, err := c.Processes() - process, err := os.FindProcess(pid) s, err := process.Wait() if err != nil { @@ -208,19 +234,7 @@ func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*o } s = execErr.ProcessState } - if err != nil { - return s, err - } - - for _, pid := range processes { - process, err := os.FindProcess(pid) - if err != nil { - log.Errorf("Failed to kill process: %d", pid) - continue - } - process.Kill() - } - + killCgroupProcs(c) p.Wait() return s, err } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index d9245c14d6..9224764955 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -3411,3 +3411,28 @@ func TestRunVolumesFromRestartAfterRemoved(t *testing.T) { logDone("run - can restart a volumes-from container after producer is removed") } + +func TestRunPidHostWithChildIsKillable(t *testing.T) { + defer deleteAllContainers() + name := "ibuildthecloud" + if out, err := exec.Command(dockerBinary, "run", "-d", "--pid=host", "--name", name, "busybox", "sh", "-c", "sleep 30; echo hi").CombinedOutput(); err != nil { + t.Fatal(err, out) + } + time.Sleep(1 * time.Second) + errchan := make(chan error) + go func() { + if out, err := exec.Command(dockerBinary, "kill", name).CombinedOutput(); err != nil { + errchan <- fmt.Errorf("%v:\n%s", err, out) + } + close(errchan) + }() + select { + case err := <-errchan: + if err != nil { + t.Fatal(err) + } + case <-time.After(5 * time.Second): + t.Fatal("Kill container timed out") + } + logDone("run - can kill container with pid-host and some childs of pid 1") +} |