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
+12 -13
View File
@@ -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
}