about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/unicorn.rb81
1 files changed, 37 insertions, 44 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index a539960..aadd7af 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -469,7 +469,7 @@ module Unicorn
       nr = 0 # this becomes negative if we need to reopen logs
       alive = worker.tempfile # tempfile is our lifeline to the master process
       ready = LISTENERS
-      client = nil
+      t = ti = Time.now.to_i
 
       # closing anything we IO.select on will raise EBADF
       trap(:USR1) { nr = -65536; SELF_PIPE.first.close rescue nil }
@@ -477,8 +477,10 @@ module Unicorn
       [:TERM, :INT].each { |sig| trap(sig) { exit!(0) } } # instant shutdown
       @logger.info "worker=#{worker.nr} ready"
 
-      while alive
-        reopen_worker_logs(worker.nr) if nr < 0
+      begin
+        nr < 0 and reopen_worker_logs(worker.nr)
+        nr = 0
+
         # we're a goner in @timeout seconds anyways if alive.chmod
         # breaks, so don't trap the exception.  Using fchmod() since
         # futimes() is not available in base Ruby and I very strongly
@@ -487,50 +489,41 @@ module Unicorn
         # changes with chmod doesn't update ctime on all filesystems; so
         # we change our counter each and every time (after process_client
         # and before IO.select).
-        alive.chmod(nr = 0)
+        t == (ti = Time.now.to_i) or alive.chmod(t = ti)
+
+        ready.each do |sock|
+          begin
+            process_client(sock.accept_nonblock)
+            nr += 1
+            t == (ti = Time.now.to_i) or alive.chmod(t = ti)
+          rescue Errno::EAGAIN, Errno::ECONNABORTED
+          end
+          break if nr < 0
+        end
 
+        # make the following bet: if we accepted clients this round,
+        # we're probably reasonably busy, so avoid calling select()
+        # and do a speculative accept_nonblock on every listener
+        # before we sleep again in select().
+        redo unless nr == 0 # (nr < 0) => reopen logs
+
+        master_pid == Process.ppid or return
+        t == (ti = Time.now.to_i) or alive.chmod(t = ti)
         begin
-          ready.each do |sock|
-            begin
-              client = begin
-                sock.accept_nonblock
-              rescue Errno::EAGAIN
-                next
-              end
-              process_client(client)
-              alive.chmod(nr += 1)
-            rescue Errno::ECONNABORTED
-              # client closed the socket even before accept
-              client.close rescue nil
-            end
-            break if nr < 0
-          end
-          client = nil
-
-          # make the following bet: if we accepted clients this round,
-          # we're probably reasonably busy, so avoid calling select()
-          # and do a speculative accept_nonblock on every listener
-          # before we sleep again in select().
-          if nr == 0 # (nr < 0) => reopen logs
-            master_pid == Process.ppid or return
-            alive.chmod(nr += 1)
-            begin
-              # timeout used so we can detect parent death:
-              ret = IO.select(LISTENERS, nil, SELF_PIPE, @timeout) or next
-              ready = ret.first
-            rescue Errno::EINTR
-              ready = LISTENERS
-            rescue Errno::EBADF => e
-              nr < 0 or exit(alive ? 1 : 0)
-            end
-          end
-        rescue Object => e
-          if alive
-            logger.error "Unhandled listen loop exception #{e.inspect}."
-            logger.error e.backtrace.join("\n")
-          end
+          # timeout used so we can detect parent death:
+          ret = IO.select(LISTENERS, nil, SELF_PIPE, @timeout) or redo
+          ready = ret.first
+        rescue Errno::EINTR
+          ready = LISTENERS
+        rescue Errno::EBADF
+          nr < 0 or return
         end
-      end
+      rescue Object => e
+        if alive
+          logger.error "Unhandled listen loop exception #{e.inspect}."
+          logger.error e.backtrace.join("\n")
+        end
+      end while alive
     end
 
     # delivers a signal to a worker and fails gracefully if the worker