diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-08-31 07:54:25 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-08-31 07:54:25 +0000 |
commit | 30ab37594677c12a4884d7199d808a8a28832549 (patch) | |
tree | 8aacde5d461a4335a96cbb58ef543276f45c6f8f | |
parent | 8c3916bfe76224b69e0f20827c4230c4e71cdc86 (diff) | |
download | zbatery-30ab37594677c12a4884d7199d808a8a28832549.tar.gz |
avoid potential Logger deadlocks in signal handling
If any combination of signals are sent to Zbatery in a short period of time, the Mutex used by the default Logger implementation may deadlock since Mutex synchronization is not reentrant-safe. By spawning a thread, we can take advantage of the thread-safety and avoid the reentrancy-safety issue of acquiring a mutex inside a signal handler. Users of alternative logger implementations (or monkey-patched ones) are possibly not affected. Users of the logger_mp_safe.rb monkey-patch distributed[1] with unicorn are not affected. [1] http://unicorn.bogomips.org/examples/logger_mp_safe.rb
-rw-r--r-- | lib/zbatery.rb | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/lib/zbatery.rb b/lib/zbatery.rb index 174ded0..8783fd4 100644 --- a/lib/zbatery.rb +++ b/lib/zbatery.rb @@ -75,16 +75,18 @@ module Rainbows end def join - trap(:INT) { stop(false) } - trap(:TERM) { stop(false) } - trap(:QUIT) { stop } - trap(:USR1) { reopen_logs } - trap(:USR2) { reexec } - trap(:HUP) { reexec; stop } + trap(:INT) { exit!(0) } + trap(:TERM) { exit!(0) } + trap(:QUIT) { Thread.new { stop } } + trap(:USR1) { Thread.new { reopen_logs } } + trap(:USR2) { Thread.new { reexec } } + trap(:HUP) { Thread.new { reexec; stop } } # technically feasible in some cases, just not sanely supportable: %w(TTIN TTOU WINCH).each do |sig| - trap(sig) { logger.info "SIG#{sig} is not handled by Zbatery" } + trap(sig) do + Thread.new { logger.info("SIG#{sig} is not handled by Zbatery") } + end end if ready_pipe |