summaryrefslogtreecommitdiff
path: root/libgo/go/os/exec/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/os/exec/exec.go')
-rw-r--r--libgo/go/os/exec/exec.go20
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 {