-
Notifications
You must be signed in to change notification settings - Fork 18k
os/exec: leaks os.pipes if cmd.Start() is never called #58369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
If you run |
@seankhliao Thanks, that is clever. Perhaps we should simply document that somewhere. |
I actually thought of that as I was writing this. I would not describe using a cancelled context as a remotely intuitive behavior though—documentation (and maybe adding to one of the examples) could help but ideally it would be simple and obvious how to use the API safely. |
I think that makes sense, and it would be the most consistent with the existing guidance that “ The workaround of calling defer func() {
if err != nil {
cmd.Wait() // Clean up any allocated pipes.
}
}() |
Another possible workaround is to call |
Currently it's safe to retry Wait if it errors on not started. Will we break people if we change that? |
If the call to (I would guess that most existing programs that call |
Maybe we should add a Close() function for this? |
I don't think it warrants a |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
What did you expect to see?
There should be some pattern I can follow to bail out and never
Start()
the command, without also leaking the pipes allocated byStdoutPipe()
andStderrPipe()
.What did you see instead?
A close reading of the latest source for the
os/Exec
module shows there is no mechanism to clean up the allocated pipes without first callingcmd.Start()
and then invokingcmd.Wait()
. While error conditions inStdoutPipe()
andStderrPipe()
should be rare (the system would likely have to run out of file descriptors), such scenarios can and do happen in production code, especially when services get stressed under load (such as during a denial of service attack). It should be possible to write "safe" code that can at least react to these scenarios and not pour more fuel on the fire (e.g. by leaking os.pipe file descriptors).Discussion
I'd be open to contributing a solution to this API limitation, but would appreciate the community's input on what an idiomatic solution would be.
The simplest approach may be to modify
cmd.Wait()
to clean up pipes even when the reason for erroring out is "not started" (e.g. https://cs.opensource.google/go/go/+/refs/tags/go1.19.5:src/os/exec/exec.go;l=594). Otherwise, a new method could be introduced for the explicit purpose of cleaning up a command without starting it (since for backwards compatibility we could not separate out the "cleanup" function fromWait
).The text was updated successfully, but these errors were encountered: