Getting list of current signal handlers without overriding, in Ruby

Lately I have been very interested about Signal handling. So, this holiday season I embarked on a teeny journey of writing a small project.

One thing I noticed when inspecting signals is that there isn’t really an easy way of doing so. Or, especially, getting the “current” action handler for a given Signal. For instance, whether a signal (TERM, INT, etc) has an action of SIG_DFL or SIG_IGN or a pointer reference.

Maybe its not a very common use case. Either way, while working on a few ruby projects, I went super deep into digging signal handling (rabbit holes?) and would have loved to access a tool that would give me the action handlers for signals. There are some ways suggested in ruby, like:

old_handler = Signal.trap("TERM", "DEFAULT")
# do something with old_handler
Signal.trap("TERM", old_handler) # restore back

Signal.trap returns the old handler for the given signal. So, here you can trap a signal with a different action and upon retrieval, restore it back and this way you can know what the “current” action is.

I found this solution a little too aggressive. Because of the non-atomicity, a lot of things can happen between overriding a signal’s action and restoring back, depending on the application.

To see how things worked internally, I went down digging ruby’s signal.c.

I loved learning more about ruby internals. I can’t wait to dive deeper and learn more about ruby and behind the scenes.

That said, basically, it boils down to how the class is using C library functionsignal (source code: here) and a few other implementations. A little about signal:

signal() sets the disposition of the signal signum to handler, which
 is either SIG_IGN, SIG_DFL, or the address of a programmer-defined
 function (a “signal handler”).

source: http://man7.org/linux/man-pages/man2/signal.2.html

Given this, I decided to explore other avenues where I can retrieve a signal’s action handler much more gracefully.

Meet SignalActionHandler

SignalActionHandler, a ruby gem, which uses C library functionsigaction (man page: link), to return the active/current action handlers on a given signal.

Example:

SignalActionHandler.info
=> {
“EXIT” => “DEFAULT”,
“HUP” => “DEFAULT”,
“INT” => “DEFAULT”,
“QUIT” => “DEFAULT”,
“ILL” => “DEFAULT”,
“TRAP” => “SYSTEM_DEFAULT”,
“ABRT” => “SYSTEM_DEFAULT”,
“IOT” => “SYSTEM_DEFAULT”,
“EMT” => “SYSTEM_DEFAULT”,
“FPE” => “SYSTEM_DEFAULT”,
...
}

Now, you can easily tell the action handlers of any signal, without having to override or restore it.

Note: The gem has a minor limitation of not being able to parse any pointer references as action handler. So, it displays them as a handler set by ruby (which is originally the case).

Writing a Ruby gem with C extension

I feel, the best part about this little holiday project was being able to write a Ruby C extension. Building a C extension in ruby is absolutely painless. The ruby C api is not very hard to understand (requires some basic C understanding but thats all) and can easily be exposed to any extension.

If you are interested in building C extensions, here are some places that I found helpful.


Lastly, if you have run into this scenario or have built similar tools around inspecting Signals, or or or… if you have any feedback on the new gem, I’d love to hear from you.