Skip to content
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/signal: impossible to make process die with SIGUSR1/SIGUSR2 #24467

Closed
glasser opened this issue Mar 21, 2018 · 3 comments
Closed

os/signal: impossible to make process die with SIGUSR1/SIGUSR2 #24467

glasser opened this issue Mar 21, 2018 · 3 comments

Comments

@glasser
Copy link
Contributor

glasser commented Mar 21, 2018

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go1.10

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

darwin amd64

What did you do?

By default on POSIX, the SIGUSR1 and SIGUSR2 asynchronous signals terminate the process when they are received.

Go's documented default for these signals (and others, but these are the ones I'm thinking about today) is to register a handler and take no action when they are received.

This is not unreasonable. However, it's a shame that there is no way to restore POSIX's default behavior of terminating due to the signal: ie, to call sigaction with SIG_DFL so that when the process receives that signal, another process wait()ing on it sees that it died with the SIGUSR1/SIGUSR2. Of course, you can signal.Notify on these signals and do an os.Exit (or syscall.Kill yourself with a more fatal signal), but you can't get SIGUSR1/SIGUSR2 into the exit status.

I noticed this because some of my project's users are running our Go binary indirectly from a Node program managed by https://github.com/remy/nodemon, a popular Node library for restarting programs during development. By default, nodemon sends SIGUSR2 to its child and all of its children as the restarting signal, and it cares specifically whether or not the killed child died due to the signal it sent or now.

(In fact, nodemon doesn't actually care if grandchildren processes which it killed with SIGUSR2 died for that reason, so in practice this issue doesn't matter in the nodemon case, but it highlighted to me that it is impossible to achieve this default POSIX behavior in Go.)

@bcmills
Copy link
Contributor

bcmills commented Mar 21, 2018

As a workaround, you can call sigaction using cgo, although that doesn't contradict your point that you can't do that in a pure Go program.

It seems like the only way to address this without cgo is to expand the signal package API, and I don't think that's something we want to do without a strong real-world use case. It sounds like it's not getting in your way at the moment — is that correct?

@glasser
Copy link
Contributor Author

glasser commented Mar 21, 2018

That is correct — I thought I had a real world use case for it but later in my debugging realized that it wasn't necessary. It is a little surprising to me that Go's list of signals that cause death by default doesn't match POSIX, but it certainly seems a little late in the game to change that one.

If you want to close this, I wouldn't object, but I just wanted this written up somewhere in case anyone else runs into the same question.

@ianlancetaylor
Copy link
Contributor

Thanks, closing for now. If we want to fix this we should add something like os/signal.Reset to reset a signal to the default behavior. It's very special purpose, though, as the only functionality not currently available would be controlling the exit status. Absent more information I don't mind asking people to use cgo for that special case.

@golang golang locked and limited conversation to collaborators Mar 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants