-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
os: StartProcess clearing O_NONBLOCK can lead to goroutine hang on Linux #43894
Comments
CC @ianlancetaylor; see also #29277 |
Change https://golang.org/cl/286352 mentions this issue: |
This is basically a dup of #29277. We pretty much have to set the file to blocking mode when we pass the descriptor to the child process. Many processes will fail if they are given a non-blocking standard input. |
Yeah, I agree. The only additional thing here is that the os.StartProcess behaviour is not documented anywhere, one has to go look at the source as far as I can tell. I understand the reasoning for stdin, stdout, stderr, but should the same apply to other files as well? It seems like touching the file status flags is best avoided as much as possible. |
Should this be closed in favor of #29277, or is it helpful to track this issue separately? I'll move this to Backlog as it seems this won't be fixed in 1.17. |
I think the only thing to do here beyond #29277 is a doc fix. Sending a CL. |
Change https://golang.org/cl/321852 mentions this issue: |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What did you do?
What did you expect to see?
The read on c returns after the goroutine calls
Close()
. The same problem exists for other syscalls like accept.What did you see instead?
The read on c blocks indefinitely. The root cause is that os.StartProcess calls
f.Fd()
which in turn callspoll.FD.SetBlocking
. That method does the following:The problem in the example I've given is that O_NONBLOCK is shared by both
f
andc
, but onlyf.isBlocking
is ever set to true. The call toc.Close()
sees thatc.isBlocking == 0
and therefore blocks while trying to acquireruntime_Semacquire(&fd.csema)
inpoll.FD.Close
. The same interaction is possible when using exec.Cmd.ExtraFiles since that just ends up calling os.StartProcess.I think there are two related problems here:
This behaviour is the root cause of a bug I fixed my library: cloudflare/tableflip@cae714b I was aware that the runtime clears O_NONBLOCK when calling
File.Fd()
while writing the library, and tried my best to avoid the problem and still got stung by this.The text was updated successfully, but these errors were encountered: