summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Morozov <lk4d4@docker.com>2015-04-10 11:04:30 -0700
committerJessica Frazelle <jess@docker.com>2015-04-13 12:28:22 -0700
commit10affa8018f5b49288a83b7ca3096504e279ca63 (patch)
tree759aeb2be7d07201712ce6168561b474e2840b5d
parentce27fa2716272e0304aae0461304ea101e0d6312 (diff)
downloaddocker-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.go44
-rw-r--r--integration-cli/docker_cli_run_test.go25
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")
+}