From fa08e1bd0b4c915add758931a5b47d2c74ebddc0 Mon Sep 17 00:00:00 2001 From: Matthias H Date: Wed, 4 Sep 2013 02:38:10 +0200 Subject: ruby 2.0.0: changes sigtrapping, fixes ThreadError Ruby 2.0.0 crashes with "ThreadError: can't be called from trap context" anytime a signal is received, because it tries to write a debug message within the "trap context". This changes signal handling so that signals are queued and processed in the main loop. More information: https://www.ruby-forum.com/topic/4411227 --- lib/rbot/ircbot.rb | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'lib/rbot/ircbot.rb') diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb index 92f5fe55..5713d175 100644 --- a/lib/rbot/ircbot.rb +++ b/lib/rbot/ircbot.rb @@ -801,6 +801,7 @@ class Bot :purge_split => @config['send.purge_split'], :truncate_text => @config['send.truncate_text'].dup + @signals = [] trap_sigs end @@ -904,26 +905,35 @@ class Bot end # things to do when we receive a signal - def got_sig(sig, func=:quit) - debug "received #{sig}, queueing #{func}" - # this is not an interruption if we just need to reconnect - $interrupted += 1 unless func == :reconnect - self.send(func) unless @quit_mutex.locked? - debug "interrupted #{$interrupted} times" - if $interrupted >= 3 - debug "drastic!" - log_session_end - exit 2 + def handle_sigs + while sig = @signals.shift + func = case sig + when 'SIGHUP' + :restart + when 'SIGUSR1' + :reconnect + else + :quit + end + debug "received #{sig}, queueing #{func}" + # this is not an interruption if we just need to reconnect + $interrupted += 1 unless func == :reconnect + self.send(func) unless @quit_mutex.locked? + debug "interrupted #{$interrupted} times" + if $interrupted >= 3 + debug "drastic!" + log_session_end + exit 2 + end end end # trap signals def trap_sigs begin - trap("SIGINT") { got_sig("SIGINT") } - trap("SIGTERM") { got_sig("SIGTERM") } - trap("SIGHUP") { got_sig("SIGHUP", :restart) } - trap("SIGUSR1") { got_sig("SIGUSR1", :reconnect) } + %w(SIGINT SIGTERM SIGHUP SIGUSR1).each do |sig| + trap(sig) { @signals << sig } + end rescue ArgumentError => e debug "failed to trap signals (#{e.pretty_inspect}): running on Windows?" rescue Exception => e @@ -1006,10 +1016,12 @@ class Bot quit_msg = nil valid_recv = false # did we receive anything (valid) from the server yet? begin + handle_sigs reconnect(quit_msg, too_fast) quit if $interrupted > 0 valid_recv = false while @socket.connected? + handle_sigs quit if $interrupted > 0 # Wait for messages and process them as they arrive. If nothing is -- cgit v1.2.3