lib/rainbows/revactor.rb in rainbows-0.5.0 vs lib/rainbows/revactor.rb in rainbows-0.6.0

- old
+ new

@@ -55,22 +55,12 @@ alive = hp.keepalive? && G.alive out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if hp.headers? HttpResponse.write(client, response, out) end while alive and hp.reset.nil? and env.clear client.close - # if we get any error, try to write something back to the client - # assuming we haven't closed the socket, but don't get hung up - # if the socket is already closed or broken. We'll always ensure - # the socket is closed at the end of this function - rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF - emergency_response(client, Const::ERROR_500_RESPONSE) - rescue HttpParserError # try to tell the client they're bad - buf.empty? or emergency_response(client, Const::ERROR_400_RESPONSE) - rescue Object => e - emergency_response(client, Const::ERROR_500_RESPONSE) - logger.error "Read error: #{e.inspect}" - logger.error e.backtrace.join("\n") + rescue => e + handle_error(client, e) end # runs inside each forked worker, this sits around and waits # for connections and doesn't die until the parent dies (or is # given a INT, QUIT, or TERM signal) @@ -99,38 +89,44 @@ listen_loop_error(e) end while G.alive end end - m = 0 - check_quit = lambda do - worker.tmp.chmod(m = 0 == m ? 1 : 0) - G.alive = false if master_pid != Process.ppid - end - begin Actor.receive do |filter| - filter.after(1, &check_quit) + filter.after(1) { G.tick } filter.when(Case[:exit, Actor, Object]) do |_,actor,_| orig = clients.size clients.delete(actor.object_id) orig >= limit and listeners.each { |l| l << :resume } - check_quit.call + G.tick end end end while G.alive || clients.size > 0 end - private - - # write a response without caring if it went out or not - # This is in the case of untrappable errors - def emergency_response(client, response_str) + # if we get any error, try to write something back to the client + # assuming we haven't closed the socket, but don't get hung up + # if the socket is already closed or broken. We'll always ensure + # the socket is closed at the end of this function + def handle_error(client, e) + msg = case e + when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF + Const::ERROR_500_RESPONSE + when HttpParserError # try to tell the client they're bad + Const::ERROR_400_RESPONSE + else + logger.error "Read error: #{e.inspect}" + logger.error e.backtrace.join("\n") + Const::ERROR_500_RESPONSE + end client.instance_eval do # this is Revactor implementation dependent - @_io.write_nonblock(response_str) rescue nil + @_io.write_nonblock(msg) + close end - client.close rescue nil + rescue + nil end def revactorize_listeners! LISTENERS.map! do |s| case s