Skip to content

Commit

Permalink
os/exec: close all internal descriptors when Cmd.Start() fails.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
briandellisanti authored and ianlancetaylor committed Apr 27, 2012
1 parent 6d1face commit a0f7c6c
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions src/pkg/os/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit a0f7c6c

Please sign in to comment.