]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/commitdiff
ruby 2.0.0: changes sigtrapping, fixes ThreadError
authorMatthias H <apoc@sixserv.org>
Wed, 4 Sep 2013 00:38:10 +0000 (02:38 +0200)
committerGiuseppe Bilotta <giuseppe.bilotta@gmail.com>
Sat, 2 Nov 2013 10:30:39 +0000 (11:30 +0100)
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

index 92f5fe55c88c400601abeb76367f2c8c189cec95..5713d1753b1e9af7ceba498062ffe5277e66edf9 100644 (file)
@@ -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