From ae58cd7710b3b31d98410421fa83f9985d69f9bc Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Fri, 17 Mar 2017 13:20:03 +0000 Subject: [PATCH] Fix stderr obtention * The Stderr pipe should be read before waiting * The Stderr pipe should not be used with Run/Output. See https://golang.org/pkg/os/exec/#Cmd.StderrPipe: Wait will close the pipe after seeing the command exit, so most callers need not close the pipe themselves; however, an implication is that it is incorrect to call Wait before all reads from the pipe have completed. For the same reason, it is incorrect to use Run when using StderrPipe. --- common/weave/client.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/common/weave/client.go b/common/weave/client.go index 77aba87b8..939e54671 100644 --- a/common/weave/client.go +++ b/common/weave/client.go @@ -9,6 +9,7 @@ import ( "net/http" "net/url" "os" + realexec "os/exec" "regexp" "strconv" @@ -196,9 +197,9 @@ func (c *client) PS() (map[string]PSEntry, error) { } } scannerErr := scanner.Err() + slurp, _ := ioutil.ReadAll(stdErr) cmdErr := cmd.Wait() if cmdErr != nil { - slurp, _ := ioutil.ReadAll(stdErr) return nil, fmt.Errorf("%s: %q", cmdErr, slurp) } if scannerErr != nil { @@ -209,14 +210,13 @@ func (c *client) PS() (map[string]PSEntry, error) { func (c *client) Expose() error { cmd := weaveCommand("--local", "ps", "weave:expose") - stdErr, err := cmd.StderrPipe() - if err != nil { - return err - } output, err := cmd.Output() if err != nil { - slurp, _ := ioutil.ReadAll(stdErr) - return fmt.Errorf("Error running weave ps: %s: %q", err, slurp) + stdErr := []byte{} + if exitErr, ok := err.(*realexec.ExitError); ok { + stdErr = exitErr.Stderr + } + return fmt.Errorf("Error running weave ps: %s: %q", err, stdErr) } ips := ipMatch.FindAllSubmatch(output, -1) if ips != nil { @@ -224,13 +224,12 @@ func (c *client) Expose() error { return nil } cmd = weaveCommand("--local", "expose") - stdErr, err = cmd.StderrPipe() - if err != nil { - return err - } - if err := cmd.Run(); err != nil { - slurp, _ := ioutil.ReadAll(stdErr) - return fmt.Errorf("Error running weave expose: %s: %q", err, slurp) + if _, err := cmd.Output(); err != nil { + stdErr := []byte{} + if exitErr, ok := err.(*realexec.ExitError); ok { + stdErr = exitErr.Stderr + } + return fmt.Errorf("Error running weave expose: %s: %q", err, stdErr) } return nil }