Skip to content

Instantly share code, notes, and snippets.

@kirs
Last active April 8, 2017 00:48
Show Gist options
  • Save kirs/351a4fc3a66124ab70bcd21c1eca39e9 to your computer and use it in GitHub Desktop.
Save kirs/351a4fc3a66124ab70bcd21c1eca39e9 to your computer and use it in GitHub Desktop.

Mixing posix threads and signal handling usually is a bit of a nightmare.

Ceri Storey, 2013

In what context is the signal handler executed?

Ruby executes the signal handler in the same thread as the parent. It can be proven by:

$stdout.sync = true
puts "parent: #{Thread.current.object_id}"
trap("TERM") { puts Thread.current.object_id }
sleep

The thread struct has interrupt_flag and interrupt_mask fields (dunno why they made it two fields).

When the signal is trapped, the current (main) thread is marked with TRAP_INTERRUPT_MASK ([1], [2]). While the thread is put on hold, VM runs the signal handler.

What is not safe to do from a signal handler?

I found only one place that explicitly forbids from being called inside a signal handler. This place is Mutex#lock. It prevents user from locking any mutex from the signal handler by the design. This is not a huge limitation, but it prevents us from using Logger which relies on Mutex. However, puts still works.

How do you log from the signal handler?

I've questioned myself: why can't you use Logger inside signal trap when Resque is doing it without any troubles? The answer is that Resque is using mono_logger, which is a mutex-free logger implementation. It works just well from the signal trap!


If you're curious, here are the spots in MRI sources that define signal trap behaviour:

Further reading:

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