about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-11-07 04:02:44 +0000
committerEric Wong <normalperson@yhbt.net>2013-11-07 05:00:11 +0000
commit9ec392b437900842a799894194f6b4c2155e604e (patch)
treec6aa3dbc3b52369f03ca32381067d3be9c4b2ce7
parent59c9c3c2c1904e74739d23f2574f0e7cdbf1a474 (diff)
downloadyahns-9ec392b437900842a799894194f6b4c2155e604e.tar.gz
apps/responses may trickle infinitely, so our QueueQuitter may
not properly kill epoll worker threads, unfortunately.  So we'll
start the timer and stop waiting (risking segfaults/ugliness) by
closing epoll descriptors
-rw-r--r--lib/yahns/queue_epoll.rb1
-rw-r--r--lib/yahns/server.rb17
2 files changed, 13 insertions, 5 deletions
diff --git a/lib/yahns/queue_epoll.rb b/lib/yahns/queue_epoll.rb
index 665b87c..3e6536b 100644
--- a/lib/yahns/queue_epoll.rb
+++ b/lib/yahns/queue_epoll.rb
@@ -59,6 +59,7 @@ class Yahns::Queue < SleepyPenguin::Epoll::IO # :nodoc:
           end
         end
       rescue => e
+        break if closed? # can still happen due to shutdown_timeout
         Yahns::Log.exception(logger, 'queue loop', e)
       end while true
     end
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index 9790783..e2d03e2 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -20,6 +20,7 @@ class Yahns::Server # :nodoc:
   include Yahns::SocketHelper
 
   def initialize(config)
+    @shutdown_expire = nil
     @shutdown_timeout = nil
     @reexec_pid = 0
     @daemon_pipe = nil # writable IO or true
@@ -379,7 +380,8 @@ class Yahns::Server # :nodoc:
 
   def quit_enter(alive)
     if alive
-      @logger.info("gracefully exiting shutdown_timeout=#{@shutdown_timeout} s")
+      @logger.info("gracefully exiting shutdown_timeout=#@shutdown_timeout")
+      @shutdown_expire ||= Time.now + @shutdown_timeout + 1
     else # drop connections immediately if signaled twice
       @logger.info("graceful exit aborted, exiting immediately")
       # we will still call any app-defined at_exit hooks here
@@ -406,7 +408,11 @@ class Yahns::Server # :nodoc:
     @queues.each { |q| q.queue_add(quitter, Yahns::Queue::QEV_QUIT) }
 
     # watch the monkey wrench destroy all the threads!
-    @wthr.delete_if { |t| t.join(0.01) } while @wthr[0]
+    # Ugh, this may fail if we have dedicated threads trickling
+    # response bodies out (e.g. "tail -F")  Oh well, have a timeout
+    begin
+      @wthr.delete_if { |t| t.join(0.01) }
+    end while @wthr[0] && Time.now <= @shutdown_expire
 
     # cleanup, our job is done
     @queues.each(&:close).clear
@@ -415,8 +421,8 @@ class Yahns::Server # :nodoc:
     Yahns::Log.exception(@logger, "quit finish", e)
   ensure
     if (@wthr.size + @listeners.size) > 0
-      @logger.error("BUG: still active wthr=#{@wthr.size} "\
-                    "listeners=#{@listeners.size}")
+      @logger.warn("still active wthr=#{@wthr.size} "\
+                   "listeners=#{@listeners.size}")
     end
   end
 
@@ -452,7 +458,8 @@ class Yahns::Server # :nodoc:
 
   def dropping(fdmap)
     if drop_acceptors[0] || fdmap.size > 0
-      fdmap.desperate_expire_for(nil, @shutdown_timeout)
+      timeout = @shutdown_expire < Time.now ? -1 : @shutdown_timeout
+      fdmap.desperate_expire_for(nil, timeout)
       true
     else
       false