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

Signal traps exit with status 0 instead of killing own process #1183

Closed
dzuelke opened this issue Dec 29, 2016 · 3 comments
Closed

Signal traps exit with status 0 instead of killing own process #1183

dzuelke opened this issue Dec 29, 2016 · 3 comments

Comments

@dzuelke
Copy link

dzuelke commented Dec 29, 2016

Steps to reproduce

  1. ruby test.rb -s Puma or whatever

  2. Ctrl+C out, or in a separate shell, killall ruby (or that process specifically)

  3. echo $?

Expected behavior

Shell prints exit status of 128+reason, where reason is e.g. 2 for SIGINT, or 15 for SIGTERM

Actual behavior

Shell prints exit status of 0

Why

Programs that exit in response to a signal must not simply exit, but instead kill themselves using the signal they trapped. This allows a calling program to determine the reason for the termination, and in some cases, such as for Ctrl+C in a shell, is essential for the system to decide how to proceed. For more information, see https://www.cons.org/cracauer/sigint.html

To verify this is intended behavior, run e.g. sleep 10, then Ctrl+C out and type echo $?, which will display "130"; or sleep 10, in a separate shell killall sleep, and in the first shell, echo $? again, which will display "143".

What the shell displays here is a convention where the reported exit status is 128+SIGNAL, and SIGNAL is the reason the program terminated.

How to fix

For example, in launcher.rb:

      begin
        Signal.trap "SIGTERM" do
          stop
          Signal.trap("SIGTERM", "DEFAULT") # restore handler
          Process.kill("TERM", 0)           # kill this process with correct signal
        end
      rescue Exception
        log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
      end

Note that exiting with SIGTERM/15 is not the same as killing the current process with SIGTERM. Exit status 128+15=143 is just how the shell displays the info, as it has no access to the lower level UNIX status functions.

@shayonj
Copy link
Contributor

shayonj commented Jun 18, 2017

Recently came across this, looks solvable, might require some tweaks to the suggested solution, to support graceful stop (will attempt at getting a PR).

While at it, I also realized, there is no trapping of SIGINT, which means ctrl + c, doesn't do a graceful stop. Is that intentional?

@shayonj
Copy link
Contributor

shayonj commented Jun 19, 2017

I have proposed a PR for TERM events. I think INT is a little tricky, since we either ignore, swallow or rescue (via Interrupt which is what ruby throws for ctrl + c) it in a number of places. To keep things simple, I have left it out the PR. I will try to take a deeper look into it and see if to what extent its solvable without issuing too much re-structure :). Happy to close the proposed PR, if we think it should all go out as a single PR.

@iGEL
Copy link

iGEL commented May 3, 2018

@nateberkopec @schneems I guess, this issue can be closed since #1337 was merged.

@evanphx evanphx closed this as completed Feb 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants