From: Russ Cox Date: Wed, 22 Jul 2015 20:50:00 +0000 (-0400) Subject: os/exec: close read pipe if copy to io.Writer fails X-Git-Tag: go1.5beta3~104 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=92390e47d81713d13b0d9890bf8b153f142a5b8a;p=gostls13.git os/exec: close read pipe if copy to io.Writer fails Fixes #10400. Change-Id: Ic486cb8af4c40660fd1a2e3d10986975acba3f19 Reviewed-on: https://go-review.googlesource.com/12537 Reviewed-by: Ian Lance Taylor --- diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index fcc37870ed..8a84e263dc 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -230,6 +230,7 @@ func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) { c.closeAfterWait = append(c.closeAfterWait, pr) c.goroutine = append(c.goroutine, func() error { _, err := io.Copy(w, pr) + pr.Close() // in case io.Copy stopped due to write error return err }) return pw, nil diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 6888d29cd8..28be21ce63 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -786,3 +786,33 @@ func TestIgnorePipeErrorOnSuccess(t *testing.T) { t.Errorf("output = %q; want %q", got, want) } } + +type badWriter struct{} + +func (w *badWriter) Write(data []byte) (int, error) { + return 0, io.ErrUnexpectedEOF +} + +func TestClosePipeOnCopyError(t *testing.T) { + testenv.MustHaveExec(t) + + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { + t.Skipf("skipping test on %s - no yes command", runtime.GOOS) + } + cmd := exec.Command("yes") + cmd.Stdout = new(badWriter) + c := make(chan int, 1) + go func() { + err := cmd.Run() + if err == nil { + t.Errorf("yes completed successfully") + } + c <- 1 + }() + select { + case <-c: + // ok + case <-time.After(5 * time.Second): + t.Fatalf("yes got stuck writing to bad writer") + } +}