diff options
Diffstat (limited to 'libgo/go/os/exec/exec.go')
-rw-r--r-- | libgo/go/os/exec/exec.go | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/libgo/go/os/exec/exec.go b/libgo/go/os/exec/exec.go index 72b4905d560..8a84e263dc8 100644 --- a/libgo/go/os/exec/exec.go +++ b/libgo/go/os/exec/exec.go @@ -32,6 +32,9 @@ func (e *Error) Error() string { } // Cmd represents an external command being prepared or run. +// +// A Cmd cannot be reused after calling its Run, Output or CombinedOutput +// methods. type Cmd struct { // Path is the path of the command to run. // @@ -80,8 +83,8 @@ type Cmd struct { // new process. It does not include standard input, standard output, or // standard error. If non-nil, entry i becomes file descriptor 3+i. // - // BUG: on OS X 10.6, child processes may sometimes inherit unwanted fds. - // http://golang.org/issue/2603 + // BUG(rsc): On OS X 10.6, child processes may sometimes inherit unwanted fds. + // https://golang.org/issue/2603 ExtraFiles []*os.File // SysProcAttr holds optional, operating system-specific attributes. @@ -154,6 +157,11 @@ func (c *Cmd) argv() []string { return []string{c.Path} } +// skipStdinCopyError optionally specifies a function which reports +// whether the provided the stdin copy error should be ignored. +// It is non-nil everywhere but Plan 9, which lacks EPIPE. See exec_posix.go. +var skipStdinCopyError func(error) bool + func (c *Cmd) stdin() (f *os.File, err error) { if c.Stdin == nil { f, err = os.Open(os.DevNull) @@ -177,6 +185,9 @@ func (c *Cmd) stdin() (f *os.File, err error) { c.closeAfterWait = append(c.closeAfterWait, pw) c.goroutine = append(c.goroutine, func() error { _, err := io.Copy(pw, c.Stdin) + if skip := skipStdinCopyError; skip != nil && skip(err) { + err = nil + } if err1 := pw.Close(); err == nil { err = err1 } @@ -219,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 @@ -352,6 +364,10 @@ func (e *ExitError) Error() string { // error is of type *ExitError. Other error types may be // returned for I/O problems. // +// If c.Stdin is not an *os.File, Wait also waits for the I/O loop +// copying from c.Stdin into the process's standard input +// to complete. +// // Wait releases any resources associated with the Cmd. func (c *Cmd) Wait() error { if c.Process == nil { |