Hello,
I need to spawn a subprocess and I'm trying to use os/exec. I need to capture
stdout/err so I'm using Cmd.StdoutPipe and Cmd.StderrPipe . The problem I'm
having is how to correctly clean up the pipes after I am done. If Cmd.Start
works fine, all I need to do is read everything and then call Cmd.Wait, which
states that it will clean up (
https://golang.org/pkg/os/exec/#Cmd.Wait ):
> Wait releases any resources associated with the Cmd.
However, what I am not sure about is how to handle cases when Cmd.Start returns
an error. Nowhere in its documentation it's said that it cleans up the
resources, so originally I thought I have to do the cleanup myself. However,
after checking the source code it does seem to close the pipes when it fails:
https://golang.org/src/os/exec/exec.go?s=11462:11489#L374And now I'm not sure what to do. io.Closer states that double-close is no-no:
> The behavior of Close after the first call is undefined.
so I cannot even close them myself (since they will be already closed). It seems
I have to rely on undocumented behaviour, but those have tendency to change and
I don't want to start leaking file descriptors after patch version update... I
assume there must be a way to solve this using just documented behaviour. Can
someone point me in a right direction?
Maybe to better show my problem, here it's in pseudo code (error handling
omitted):
cmd := exec.Command(name, args...)
stdout, _ := cmd.StdoutPipe()
stderr, _ := cmd.StderrPipe()
if err := cmd.Start(); err != nil {
// --> How should I close stdout/stderr here to future-proof for
// changes in cmd.Start behavior?
return err
}
consumeAll(stdout)
consumeAll(stderr)
cmd.Wait()
return nil
Thank you,
Tomas Volf