-
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: process.Wait marks the process as already finished on ptrace stop signals on Linux #60321
Comments
Thanks for the bug report. I don't understand why this is happening. We call
but why does |
A good catch. Go uses So one way to fix this is to use BTW, I could not find anywhere explicitly documented that
So maybe the same "Status for traced children which have stopped is provided even if this option is not specified." holds for BSD seems to have clearer options here:
|
Isn't that required by POSIX?
It goes on to describe https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html does give some detail about
At any rate, I wonder if the Linux |
A nice find indeed. Now that I know what to look for it is interesting that this man page says nothing about it, but this one does:
|
Using pidfd allows us to have a handle on the process and poll the handle to non-blocking wait for the process to exit. Fixes golang#34396 Fixes golang#60321 Fixes golang#60320
I made a draft in #60461 which addresses this. See Gerrit for some of my comments. It is not yet perfect but it does fix the issue here. |
Using pidfd allows us to have a handle on the process and poll the handle to non-blocking wait for the process to exit. Fixes golang#34396 Fixes golang#60321 Fixes golang#60320
Change https://go.dev/cl/498615 mentions this issue: |
Interesting; the (https://man7.org/linux/man-pages/man2/waitid.2.html also includes the update.) |
I just finished the comments now. |
So while working on this I think there are two ways to address this: pidfd helps here because it allows us to really detect exit and just exit so we do not have to call wait unnecessary. But another solution is to simply expand cases when we loop around wait and do another wait if wait returned for any other reason than exit/signal (we could do such a loop in blockUntilWaitable as well, which is not necessary with pidfd approach). |
Using pidfd allows us to have a handle on the process and poll the handle to non-blocking wait for the process to exit. Fixes golang#34396 Fixes golang#60321 Fixes golang#60320
A loop sounds good if it works, but would it work? If a process is stopped due to |
A good point. I tested this now (by removing |
(This is helpful behavior for this particular problem, but for my own init program in fact means that only one wait in the process succeeds and if there are multiple waits for the same process (e.g., one by pid and one using -1, like a wait loop to reap unknown reparented processes to the init), it is arbitrary which one will succeed and which one will stay blocked. And there is no timeout to blocking.) |
I have read through kernel code and I do not think that the patch linked above broke this. That patch deals with the question if threads or not are waited on by default. And if thread is ptraced, then it is waited on. From looking at the code it seems that wait simply always waits on all signals from ptraced processes. I also tested this by calling |
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?
https://go.dev/play/p/PYGxV0Kg3pF
What did you expect to see?
Or nothing, if process.Wait returns only on exit status and not stopped status.
What did you see instead?
The text was updated successfully, but these errors were encountered: