-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Closed
Labels
Milestone
Description
Writer set to exec.Cmd.Stdout (or Stderr) may fail. When that happens, underlying pipe is not closed, and command continues to run without noticing that something is wrong.
Here is an example. This little program starts "ls -lR /", which (usually) runs for a long time and produces lot of output. When our brokenWriter returns error, ls command continues to run. Buffer associated with the pipe in the kernel eventually gets filled, which in turn blocks ls, which will then never finish.
I think the solution is to close underlying pr pipe when goroutine created by Cmd.writerDescriptor detects error, similar to what goroutine in stdin method does
package main
import "os"
import "os/exec"
import "io"
import "log"
import "fmt"
type brokenWriter struct {
w io.Writer
c int
}
func (bw *brokenWriter) Write(data []byte) (int, error) {
if bw.c > 0 {
bw.c = bw.c - 1
return bw.w.Write(data)
}
log.Println("returning error from broken writer")
return 0, fmt.Errorf("broken writer")
}
func main() {
cmd := exec.Command("ls", "-lR", "/")
cmd.Stdout = &brokenWriter{os.Stdout, 1}
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}