pass extra file to child process as status handler

When stdout/stderr is closed prematurely, the proxy's writes to stdout/stderr
(i.e. `log.Errorf/log.Printf`) will returns with EPIPE error, and go runtime
will terminate the proxy when stdout/stderr writes trigger 10 EPIPE errors.

instead of using stdout/stderr as the status handler, we pass an extra file to
the child process and write `0\n` or `1\nerror message` to it and close it
after. This allow the child process to handle stdout/stderr as normal.

Docker-DCO-1.1-Signed-off-by: Daniel, Dao Quang Minh <dqminh89@gmail.com> (github: dqminh)
This commit is contained in:
Daniel, Dao Quang Minh
2014-10-08 12:53:43 -04:00
parent 7813f85e7d
commit 3b9d88210e
2 changed files with 45 additions and 13 deletions
+33
View File
@@ -2093,6 +2093,39 @@ func TestRunPortInUse(t *testing.T) {
logDone("run - fail if port already in use")
}
// https://github.com/docker/docker/issues/8428
func TestRunPortProxy(t *testing.T) {
defer deleteAllContainers()
port := "12345"
cmd := exec.Command(dockerBinary, "run", "-p", port+":80", "busybox", "true")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("Failed to run and bind port %s, output: %s, error: %s", port, out, err)
}
// connect for 10 times here. This will trigger 10 EPIPES in the child
// process and kill it when it writes to a closed stdout/stderr
for i := 0; i < 10; i++ {
net.Dial("tcp", fmt.Sprintf("0.0.0.0:%s", port))
}
listPs := exec.Command("sh", "-c", "ps ax | grep docker")
out, _, err = runCommandWithOutput(listPs)
if err != nil {
t.Errorf("list docker process failed with output %s, error %s", out, err)
}
if strings.Contains(out, "docker <defunct>") {
t.Errorf("Unexpected defunct docker process")
}
if !strings.Contains(out, "docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 12345") {
t.Errorf("Failed to find docker-proxy process, got %s", out)
}
logDone("run - proxy should work with unavailable port")
}
// Regression test for #7792
func TestRunMountOrdering(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "docker_nested_mount_test")