]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/ircbot.rb
* make the daemonization thing to suck less (wrt standard io channels)
[user/henk/code/ruby/rbot.git] / lib / rbot / ircbot.rb
index cd073b327448f6a054889bea2869c051b8337f36..6a1c8f6758472f9ba5da84ba432b594e298947b4 100644 (file)
@@ -18,6 +18,9 @@ $logger.datetime_format = $dateformat
 $logger.level = $cl_loglevel if defined? $cl_loglevel
 $logger.level = 0 if $debug
 
+$log_queue = Queue.new
+$log_thread = nil
+
 require 'pp'
 
 unless Kernel.instance_methods.include?("pretty_inspect")
@@ -39,37 +42,55 @@ class Exception
 end
 
 def rawlog(level, message=nil, who_pos=1)
-  begin
-    call_stack = caller
-    if call_stack.length > who_pos
-      who = call_stack[who_pos].sub(%r{(?:.+)/([^/]+):(\d+)(:in .*)?}) { "#{$1}:#{$2}#{$3}" }
-    else
-      who = "(unknown)"
-    end
-    # Output each line. To distinguish between separate messages and multi-line
-    # messages originating at the same time, we blank #{who} after the first message
-    # is output.
-    # Also, we output strings as-is but for other objects we use pretty_inspect
-    case message
-    when String
-      str = message
-    else
-      str = message.pretty_inspect
+  call_stack = caller
+  if call_stack.length > who_pos
+    who = call_stack[who_pos].sub(%r{(?:.+)/([^/]+):(\d+)(:in .*)?}) { "#{$1}:#{$2}#{$3}" }
+  else
+    who = "(unknown)"
+  end
+  # Output each line. To distinguish between separate messages and multi-line
+  # messages originating at the same time, we blank #{who} after the first message
+  # is output.
+  # Also, we output strings as-is but for other objects we use pretty_inspect
+  case message
+  when String
+    str = message
+  else
+    str = message.pretty_inspect
+  end
+  qmsg = Array.new
+  str.each_line { |l|
+    qmsg.push [level, l.chomp, who]
+    who = ' ' * who.size
+  }
+  $log_queue.push qmsg
+end
+
+def restart_logger
+  if $log_thread && $log_thread.alive?
+    $log_queue << nil
+    $log_thread.join
+    $log_thread = nil
+  end
+
+  $log_thread = Thread.new do
+    ls = nil
+    while ls = $log_queue.pop
+      ls.each { |l| $logger.add(*l) }
     end
-    str.each_line { |l|
-      $logger.add(level, l.chomp, who)
-      who.gsub!(/./," ")
-    }
-  rescue SecurityError
   end
 end
 
+restart_logger
+
 def log_session_start
   $logger << "\n\n=== #{botclass} session started on #{Time.now.strftime($dateformat)} ===\n\n"
+  restart_logger
 end
 
 def log_session_end
   $logger << "\n\n=== #{botclass} session ended on #{Time.now.strftime($dateformat)} ===\n\n"
+  $log_queue << nil
 end
 
 def debug(message=nil, who_pos=1)
@@ -442,17 +463,20 @@ class Bot
       Dir.chdir botclass
       # File.umask 0000                # Ensure sensible umask. Adjust as needed.
       log "Redirecting standard input/output/error"
-      begin
-        STDIN.reopen "/dev/null"
-      rescue Errno::ENOENT
-        # On Windows, there's not such thing as /dev/null
-        STDIN.reopen "NUL"
+      [$stdin, $stdout, $stderr].each do |fd|
+        begin
+          fd.reopen "/dev/null"
+        rescue Errno::ENOENT
+          # On Windows, there's not such thing as /dev/null
+          fd.reopen "NUL"
+        end
       end
-      def STDOUT.write(str=nil)
+
+      def $stdout.write(str=nil)
         log str, 2
         return str.to_s.size
       end
-      def STDERR.write(str=nil)
+      def $stdout.write(str=nil)
         if str.to_s.match(/:\d+: warning:/)
           warning str, 2
         else
@@ -1065,9 +1089,11 @@ class Bot
       # now we re-exec
       # Note, this fails on Windows
       debug "going to exec #{$0} #{@argv.inspect} from #{@run_dir}"
+      log_session_end
       Dir.chdir(@run_dir)
       exec($0, *@argv)
     rescue Errno::ENOENT
+      log_session_end
       exec("ruby", *(@argv.unshift $0))
     rescue Exception => e
       $interrupted += 1