Sfoglia il codice sorgente

Fix LXC stop signals

`lxc-stop` does not support sending arbitrary signals.
By default, `lxc-stop -n <id>` would send `SIGPWR`.
The lxc driver was always sending `lxc-stop -n <id> -k`, which always
sends `SIGKILL`. In this case `lxc-start` returns an exit code of `0`,
regardless of what the container actually exited with.
Because of this we must send signals directly to the process when we
can.

Also need to set quiet mode on `lxc-start` otherwise it reports an error
on `stderr` when the container exits cleanly (ie, we didn't SIGKILL it),
this error is picked up in the container logs... and isn't really an
error.

Also cleaned up some potential races for waitblocked test.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Brian Goff 10 anni fa
parent
commit
d2c4ee37c6
2 ha cambiato i file con 32 aggiunte e 11 eliminazioni
  1. 11 4
      daemon/execdriver/lxc/driver.go
  2. 21 7
      integration-cli/docker_cli_wait_test.go

+ 11 - 4
daemon/execdriver/lxc/driver.go

@@ -127,6 +127,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 		"lxc-start",
 		"lxc-start",
 		"-n", c.ID,
 		"-n", c.ID,
 		"-f", configPath,
 		"-f", configPath,
+		"-q",
 	}
 	}
 
 
 	// From lxc>=1.1 the default behavior is to daemonize containers after start
 	// 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)
 	oomKillNotification, err := notifyOnOOM(cgroupPaths)
 
 
 	<-waitLock
 	<-waitLock
+	exitCode := getExitCode(c)
 
 
 	if err == nil {
 	if err == nil {
 		_, oomKill = <-oomKillNotification
 		_, oomKill = <-oomKillNotification
-		logrus.Debugf("oomKill error %s waitErr %s", oomKill, waitErr)
+		logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr)
 	} else {
 	} else {
 		logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
 		logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
 	}
 	}
 
 
 	// check oom error
 	// check oom error
-	exitCode := getExitCode(c)
 	if oomKill {
 	if oomKill {
 		exitCode = 137
 		exitCode = 137
 	}
 	}
+
 	return execdriver.ExitStatus{ExitCode: exitCode, OOMKilled: oomKill}, waitErr
 	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 {
 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 {
 func (d *driver) Pause(c *execdriver.Command) error {
@@ -528,7 +534,8 @@ func KillLxc(id string, sig int) error {
 	if err == nil {
 	if err == nil {
 		output, err = exec.Command("lxc-kill", "-n", id, strconv.Itoa(sig)).CombinedOutput()
 		output, err = exec.Command("lxc-kill", "-n", id, strconv.Itoa(sig)).CombinedOutput()
 	} else {
 	} 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 {
 	if err != nil {
 		return fmt.Errorf("Err: %s Output: %s", err, output)
 		return fmt.Errorf("Err: %s Output: %s", err, output)

+ 21 - 7
integration-cli/docker_cli_wait_test.go

@@ -1,6 +1,7 @@
 package main
 package main
 
 
 import (
 import (
+	"bytes"
 	"os/exec"
 	"os/exec"
 	"strings"
 	"strings"
 	"time"
 	"time"
@@ -44,7 +45,7 @@ func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) {
 
 
 // blocking wait with 0 exit code
 // blocking wait with 0 exit code
 func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) {
 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)
 	containerID := strings.TrimSpace(out)
 
 
 	if err := waitRun(containerID); err != nil {
 	if err := waitRun(containerID); err != nil {
@@ -107,7 +108,7 @@ func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) {
 
 
 // blocking wait with random exit code
 // blocking wait with random exit code
 func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
 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)
 	containerID := strings.TrimSpace(out)
 	if err := waitRun(containerID); err != nil {
 	if err := waitRun(containerID); err != nil {
 		c.Fatal(err)
 		c.Fatal(err)
@@ -116,21 +117,34 @@ func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
 		c.Fatal(err)
 		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() {
 	go func() {
-		out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "wait", containerID))
-		chWait <- out
+		chWait <- waitCmd.Wait()
 	}()
 	}()
 
 
-	time.Sleep(100 * time.Millisecond)
 	dockerCmd(c, "stop", containerID)
 	dockerCmd(c, "stop", containerID)
 
 
 	select {
 	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" {
 		if strings.TrimSpace(status) != "99" {
 			c.Fatalf("expected exit 99, got %s", status)
 			c.Fatalf("expected exit 99, got %s", status)
 		}
 		}
 	case <-time.After(2 * time.Second):
 	case <-time.After(2 * time.Second):
+		waitCmd.Process.Kill()
 		c.Fatal("timeout waiting for `docker wait` to exit")
 		c.Fatal("timeout waiting for `docker wait` to exit")
 	}
 	}
 }
 }