lib/zeus/server/acceptor.rb in zeus-0.4.4 vs lib/zeus/server/acceptor.rb in zeus-0.4.5

- old
+ new

@@ -2,57 +2,33 @@ require 'socket' # See Zeus::Server::ClientHandler for relevant documentation module Zeus class Server - class Acceptor < ForkedProcess - attr_accessor :aliases, :description, :action + class Acceptor + attr_accessor :aliases, :description, :action, :name + def initialize(server) + @server = server + end def descendent_acceptors self end - def before_setup + def run register_with_client_handler(Process.pid) - end + Zeus.ui.info("starting #{process_type} `#{@name}`") - def runloop! - loop do - prefork_action! - terminal, arguments = accept_connection # blocking - child = fork { __RUNNER__run(terminal, arguments) } - terminal.close - - Process.detach(child) - end + thread_with_backtrace_on_error { runloop! } end - def __RUNNER__run(terminal, arguments) - $0 = "zeus runner: #{@name}" - Process.setsid - postfork_action! - @s_acceptor << $$ << "\n" - $stdin.reopen(terminal) - $stdout.reopen(terminal) - $stderr.reopen(terminal) - ARGV.replace(arguments) + private - @action.call - ensure - # TODO this is a whole lot of voodoo that I don't really understand. - # I need to figure out how best to make the process disconenct cleanly. - dnw, dnr = File.open("/dev/null", "w+"), File.open("/dev/null", "r+") - $stderr.reopen(dnr) - $stdout.reopen(dnr) - terminal.close - $stdin.reopen(dnw) - Process.kill(9, $$) - exit 0 + def command_runner + CommandRunner.new(name, action, @s_acceptor) end - private - def register_with_client_handler(pid) @s_client_handler, @s_acceptor = UNIXSocket.pair @s_acceptor.puts registration_data(pid) @server.__CHILD__register_acceptor(@s_client_handler) end @@ -70,44 +46,48 @@ def process_type "acceptor" end + def print_error(io, error) + io.puts "#{error.backtrace[0]}: #{error.message} (#{error.class})" + error.backtrace[1..-1].each do |line| + io.puts "\tfrom #{line}" + end + end - # these two methods should be part of the configuration DSL. - # They're here for now, but I want them out. - def prefork_action! # TODO : refactor - ActiveRecord::Base.clear_all_connections! rescue nil + def thread_with_backtrace_on_error(&b) + Thread.new { + begin + b.call + rescue => e + print_error($stdout, e) + end + } end - def postfork_action! # TODO :refactor - ActiveRecord::Base.establish_connection rescue nil - # ActiveSupport::DescendantsTracker.clear rescue nil - # ActiveSupport::Dependencies.clear rescue nil + def runloop! + loop do + terminal, arguments = accept_connection # blocking + command_runner.run(terminal, arguments) + end end module ErrorState + NOT_A_PID = 0 attr_accessor :error - def print_error(io, error = @error) - io.puts "#{error.backtrace[0]}: #{error.message} (#{error.class})" - error.backtrace[1..-1].each do |line| - io.puts "\tfrom #{line}" - end + def process_type + "error-state acceptor" end - def run - register_with_client_handler(Process.pid) - Zeus.ui.info "starting error-state acceptor `#{@name}`" - - Thread.new do - loop do - terminal = @s_acceptor.recv_io - _ = @s_acceptor.readline - @s_acceptor << 0 << "\n" - print_error(terminal) - terminal.close - end + def runloop! + loop do + terminal = @s_acceptor.recv_io + _ = @s_acceptor.readline + @s_acceptor << NOT_A_PID << "\n" + print_error(terminal, @error) + terminal.close end end end end