mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
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:
parent
7813f85e7d
commit
3b9d88210e
2 changed files with 45 additions and 13 deletions
|
@ -36,16 +36,18 @@ type proxyCommand struct {
|
|||
|
||||
// execProxy is the reexec function that is registered to start the userland proxies
|
||||
func execProxy() {
|
||||
f := os.NewFile(3, "signal-parent")
|
||||
host, container := parseHostContainerAddrs()
|
||||
|
||||
p, err := proxy.NewProxy(host, container)
|
||||
if err != nil {
|
||||
os.Stdout.WriteString("1\n")
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
fmt.Fprintf(f, "1\n%s", err)
|
||||
f.Close()
|
||||
os.Exit(1)
|
||||
}
|
||||
go handleStopSignals(p)
|
||||
os.Stdout.WriteString("0\n")
|
||||
fmt.Fprint(f, "0\n")
|
||||
f.Close()
|
||||
|
||||
// Run will block until the proxy stops
|
||||
p.Run()
|
||||
|
@ -111,27 +113,24 @@ func NewProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.
|
|||
}
|
||||
|
||||
func (p *proxyCommand) Start() error {
|
||||
stdout, err := p.cmd.StdoutPipe()
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("proxy unable to open os.Pipe %s", err)
|
||||
}
|
||||
defer stdout.Close()
|
||||
stderr, err := p.cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stderr.Close()
|
||||
defer r.Close()
|
||||
p.cmd.ExtraFiles = []*os.File{w}
|
||||
if err := p.cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
w.Close()
|
||||
|
||||
errchan := make(chan error, 1)
|
||||
go func() {
|
||||
buf := make([]byte, 2)
|
||||
stdout.Read(buf)
|
||||
r.Read(buf)
|
||||
|
||||
if string(buf) != "0\n" {
|
||||
errStr, _ := ioutil.ReadAll(stderr)
|
||||
errStr, _ := ioutil.ReadAll(r)
|
||||
errchan <- fmt.Errorf("Error starting userland proxy: %s", errStr)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in a new issue