From: Brian Dellisanti Date: Wed, 13 Jun 2012 20:23:36 +0000 (-0400) Subject: [release-branch.go1] os/exec: close all internal descriptors when Cmd.Start() fails. X-Git-Tag: go1.0.2~106 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=43f2be4f4b16c9ff0cebf97fc022e20a977b5868;p=gostls13.git [release-branch.go1] os/exec: close all internal descriptors when Cmd.Start() fails. ««« backport 9d046474e95a os/exec: close all internal descriptors when Cmd.Start() fails. This closes any internal descriptors (pipes, etc) that Cmd.Start() had opened before it failed. Fixes #3468. R=golang-dev, iant, bradfitz CC=golang-dev https://golang.org/cl/5986044 »»» --- diff --git a/src/pkg/os/exec/exec.go b/src/pkg/os/exec/exec.go index bbd04902b7..9a8e181701 100644 --- a/src/pkg/os/exec/exec.go +++ b/src/pkg/os/exec/exec.go @@ -204,6 +204,12 @@ func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) { return pw, nil } +func (c *Cmd) closeDescriptors(closers []io.Closer) { + for _, fd := range closers { + fd.Close() + } +} + // Run starts the specified command and waits for it to complete. // // The returned error is nil if the command runs, has no problems @@ -233,6 +239,8 @@ func (c *Cmd) Start() error { for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { fd, err := setupFd(c) if err != nil { + c.closeDescriptors(c.closeAfterStart) + c.closeDescriptors(c.closeAfterWait) return err } c.childFiles = append(c.childFiles, fd) @@ -247,12 +255,12 @@ func (c *Cmd) Start() error { Sys: c.SysProcAttr, }) if err != nil { + c.closeDescriptors(c.closeAfterStart) + c.closeDescriptors(c.closeAfterWait) return err } - for _, fd := range c.closeAfterStart { - fd.Close() - } + c.closeDescriptors(c.closeAfterStart) c.errch = make(chan error, len(c.goroutine)) for _, fn := range c.goroutine { @@ -301,9 +309,7 @@ func (c *Cmd) Wait() error { } } - for _, fd := range c.closeAfterWait { - fd.Close() - } + c.closeDescriptors(c.closeAfterWait) if err != nil { return err