diff --git a/components/engine/daemon/execdriver/lxc/driver.go b/components/engine/daemon/execdriver/lxc/driver.go index 32e5b43ebc..49db608743 100644 --- a/components/engine/daemon/execdriver/lxc/driver.go +++ b/components/engine/daemon/execdriver/lxc/driver.go @@ -127,6 +127,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba "lxc-start", "-n", c.ID, "-f", configPath, + "-q", } // From lxc>=1.1 the default behavior is to daemonize containers after start @@ -278,19 +279,20 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba oomKillNotification, err := notifyOnOOM(cgroupPaths) <-waitLock + exitCode := getExitCode(c) if err == nil { _, oomKill = <-oomKillNotification - logrus.Debugf("oomKill error %s waitErr %s", oomKill, waitErr) + logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr) } else { logrus.Warnf("Your kernel does not support OOM notifications: %s", err) } // check oom error - exitCode := getExitCode(c) if oomKill { exitCode = 137 } + return execdriver.ExitStatus{ExitCode: exitCode, OOMKilled: oomKill}, waitErr } @@ -468,7 +470,11 @@ func getExitCode(c *execdriver.Command) int { } func (d *driver) Kill(c *execdriver.Command, sig int) error { - return KillLxc(c.ID, sig) + if sig == 9 || c.ProcessConfig.Process == nil { + return KillLxc(c.ID, sig) + } + + return c.ProcessConfig.Process.Signal(syscall.Signal(sig)) } func (d *driver) Pause(c *execdriver.Command) error { @@ -528,7 +534,8 @@ func KillLxc(id string, sig int) error { if err == nil { output, err = exec.Command("lxc-kill", "-n", id, strconv.Itoa(sig)).CombinedOutput() } else { - output, err = exec.Command("lxc-stop", "-k", "-n", id, strconv.Itoa(sig)).CombinedOutput() + // lxc-stop does not take arbitrary signals like lxc-kill does + output, err = exec.Command("lxc-stop", "-k", "-n", id).CombinedOutput() } if err != nil { return fmt.Errorf("Err: %s Output: %s", err, output) diff --git a/components/engine/integration-cli/docker_cli_wait_test.go b/components/engine/integration-cli/docker_cli_wait_test.go index 21f04faf0f..b7fb3fe958 100644 --- a/components/engine/integration-cli/docker_cli_wait_test.go +++ b/components/engine/integration-cli/docker_cli_wait_test.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "os/exec" "strings" "time" @@ -44,7 +45,7 @@ func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) { // blocking wait with 0 exit code func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) { - out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 0' SIGTERM; while true; do sleep 0.01; done") + out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 0' TERM; while true; do sleep 0.01; done") containerID := strings.TrimSpace(out) if err := waitRun(containerID); err != nil { @@ -107,7 +108,7 @@ func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) { // blocking wait with random exit code func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) { - out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "trap 'exit 99' SIGTERM; while true; do sleep 0.01; done") + out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 99' TERM; while true; do sleep 0.01; done") containerID := strings.TrimSpace(out) if err := waitRun(containerID); err != nil { c.Fatal(err) @@ -116,21 +117,34 @@ func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) { c.Fatal(err) } - chWait := make(chan string) + chWait := make(chan error) + waitCmd := exec.Command(dockerBinary, "wait", containerID) + waitCmdOut := bytes.NewBuffer(nil) + waitCmd.Stdout = waitCmdOut + if err := waitCmd.Start(); err != nil { + c.Fatal(err) + } + go func() { - out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "wait", containerID)) - chWait <- out + chWait <- waitCmd.Wait() }() - time.Sleep(100 * time.Millisecond) dockerCmd(c, "stop", containerID) select { - case status := <-chWait: + case err := <-chWait: + if err != nil { + c.Fatal(err) + } + status, err := waitCmdOut.ReadString('\n') + if err != nil { + c.Fatal(err) + } if strings.TrimSpace(status) != "99" { c.Fatalf("expected exit 99, got %s", status) } case <-time.After(2 * time.Second): + waitCmd.Process.Kill() c.Fatal("timeout waiting for `docker wait` to exit") } }