Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active October 14, 2024 02:08
Show Gist options
  • Save x-yuri/214eadf87001484e1ced9b508d0726cd to your computer and use it in GitHub Desktop.
Save x-yuri/214eadf87001484e1ced9b508d0726cd to your computer and use it in GitHub Desktop.
ruby and SIGTERM

ruby and SIGTERM

I'm going to consider 2 cases:

  1. No signal handler was registered:

    ruby -e sleep
  2. A signal handler was registered:

    ruby -e 'Signal.trap("TERM") do puts "SIGTERM" end; sleep'

On initialization ruby sets a SIGTERM handler:

On receiving SIGTERM it puts it into a queue:

And when it has time it tries to execute the user handler (if it was registered):

If there's no signal handler, it raises an exception. If there is, it invokes it.

Another way to confirm this:

$ docker run --rm ruby:3.3.5-alpine3.20 \
    sh -euc 'apk add strace && strace -e trace=rt_sigaction ruby --disable gems -e "" 2>&1 | grep TERM'
rt_sigaction(SIGTERM, {sa_handler=0x7aa469668bb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7aa469acefeb}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0

Apparently ruby does this to delay execution of signal handlers to a moment where it's safe to execute them. It's probably the reason similar to the one explained in the perl docs:

Prior to Perl 5.8.0 it was necessary to do as little as you possibly could in your handler; notice how all we do is set a global variable and then raise an exception. That's because on most systems, libraries are not re-entrant; particularly, memory allocation and I/O routines are not. That meant that doing nearly anything in your handler could in theory trigger a memory fault and subsequent core dump - see "Deferred Signals (Safe Signals)" below.

https://perldoc.perl.org/perlipc#Signals

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment