X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=lib%2Frbot%2Fircbot.rb;h=3cd0cae844d2584a5d8647edba4e309937993fac;hb=7c0c7d49240c56124ba0d99a14f6d7156317c499;hp=d95eb18dad94bb2edd8d3b678d2a04ed5b66d72b;hpb=fcda5169000a33c237bb6b0ed28afcf29a674ffd;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb index d95eb18d..3cd0cae8 100644 --- a/lib/rbot/ircbot.rb +++ b/lib/rbot/ircbot.rb @@ -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") @@ -55,18 +58,47 @@ def rawlog(level, message=nil, who_pos=1) else str = message.pretty_inspect end + qmsg = Array.new str.each_line { |l| - $logger.add(level, l.chomp, who) - who.gsub!(/./," ") + qmsg.push [level, l.chomp, who] + who = ' ' * who.size } + $log_queue.push qmsg end +def halt_logger + if $log_thread && $log_thread.alive? + $log_queue << nil + $log_thread.join + $log_thread = nil + end +end + +END { halt_logger } + +def restart_logger(newlogger = false) + halt_logger + + $logger = newlogger if newlogger + + $log_thread = Thread.new do + ls = nil + while ls = $log_queue.pop + ls.each { |l| $logger.add(*l) } + end + 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) @@ -420,6 +452,7 @@ class Bot @logfile = @config['log.file'] if @logfile.class!=String || @logfile.empty? @logfile = "#{botclass}/#{File.basename(botclass).gsub(/^\.+/,'')}.log" + debug "Using `#{@logfile}' as debug log" end # See http://blog.humlab.umu.se/samuel/archives/000107.html @@ -438,18 +471,36 @@ class Bot end Dir.chdir botclass # File.umask 0000 # Ensure sensible umask. Adjust as needed. + end + + logger = Logger.new(@logfile, + @config['log.keep'], + @config['log.max_size']*1024*1024) + logger.datetime_format= $dateformat + logger.level = @config['log.level'] + logger.level = $cl_loglevel if defined? $cl_loglevel + logger.level = 0 if $debug + + restart_logger(logger) + + log_session_start + + if $daemonize 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 @@ -459,15 +510,6 @@ class Bot end end - # Set the new logfile and loglevel. This must be done after the daemonizing - $logger = Logger.new(@logfile, @config['log.keep'], @config['log.max_size']*1024*1024) - $logger.datetime_format= $dateformat - $logger.level = @config['log.level'] - $logger.level = $cl_loglevel if defined? $cl_loglevel - $logger.level = 0 if $debug - - log_session_start - File.open($opts['pidfile'] || "#{@botclass}/rbot.pid", 'w') do |pf| pf << "#{$$}\n" end @@ -522,7 +564,7 @@ class Bot # Array of channels names where the bot should be quiet # '*' means all channels # - @quiet = [] + @quiet = Set.new @client[:welcome] = proc {|data| m = WelcomeMessage.new(self, server, data[:source], data[:target], data[:message]) @@ -575,8 +617,7 @@ class Bot @client[:notice] = proc { |data| message = NoticeMessage.new(self, server, data[:source], data[:target], data[:message]) # pass it off to plugins that want to hear everything - @plugins.delegate "listen", message - @plugins.delegate "notice", message + @plugins.irc_delegate "notice", message } @client[:motd] = proc { |data| m = MotdMessage.new(self, server, data[:source], data[:target], data[:motd]) @@ -630,6 +671,7 @@ class Bot } @client[:join] = proc {|data| m = JoinMessage.new(self, server, data[:source], data[:channel], data[:message]) + sendq("MODE #{data[:channel]}", nil, 0) if m.address? @plugins.irc_delegate("join", m) sendq("WHO #{data[:channel]}", data[:channel], 2) if m.address? } @@ -678,6 +720,8 @@ class Bot :split_at => Regexp.new(@config['send.split_at']), :purge_split => @config['send.purge_split'], :truncate_text => @config['send.truncate_text'].dup + + trap_sigs end def setup_plugins_path @@ -716,17 +760,17 @@ class Bot return @quiet.include?('*') || @quiet.include?(channel.downcase) end - def set_quiet(channel) + def set_quiet(channel = nil) if channel ch = channel.downcase.dup - @quiet << ch unless @quiet.include?(ch) + @quiet << ch else @quiet.clear @quiet << '*' end end - def reset_quiet(channel) + def reset_quiet(channel = nil) if channel @quiet.delete channel.downcase else @@ -735,10 +779,10 @@ class Bot end # things to do when we receive a signal - def got_sig(sig) - debug "received #{sig}, queueing quit" + def got_sig(sig, func=:quit) + debug "received #{sig}, queueing #{func}" $interrupted += 1 - quit unless @quit_mutex.locked? + self.send(func) unless @quit_mutex.locked? debug "interrupted #{$interrupted} times" if $interrupted >= 3 debug "drastic!" @@ -747,17 +791,21 @@ class Bot end end - # connect the bot to IRC - def connect + # trap signals + def trap_sigs begin trap("SIGINT") { got_sig("SIGINT") } trap("SIGTERM") { got_sig("SIGTERM") } - trap("SIGHUP") { got_sig("SIGHUP") } + trap("SIGHUP") { got_sig("SIGHUP", :restart) } rescue ArgumentError => e debug "failed to trap signals (#{e.pretty_inspect}): running on Windows?" rescue Exception => e debug "failed to trap signals: #{e.pretty_inspect}" end + end + + # connect the bot to IRC + def connect begin quit if $interrupted > 0 @socket.connect @@ -999,7 +1047,7 @@ class Bot debug "Sending quit message" @socket.emergency_puts "QUIT :#{message}" debug "Logging quits" - delegate_sent('QUIT', @bot.myself, message) + delegate_sent('QUIT', myself, message) debug "Flushing socket" @socket.flush rescue SocketError => e @@ -1063,9 +1111,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