about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/yahns/fdmap.rb11
-rw-r--r--lib/yahns/server.rb3
-rw-r--r--lib/yahns/server_mp.rb2
-rw-r--r--test/test_server.rb35
4 files changed, 45 insertions, 6 deletions
diff --git a/lib/yahns/fdmap.rb b/lib/yahns/fdmap.rb
index fab5d36..0aaf360 100644
--- a/lib/yahns/fdmap.rb
+++ b/lib/yahns/fdmap.rb
@@ -89,10 +89,10 @@ class Yahns::Fdmap # :nodoc:
   # We should not be calling this too frequently, it is expensive
   # This is called while @fdmap_mtx is held
   def __expire(timeout)
-    return if @count == 0
+    return 0 if @count == 0
     nr = 0
     now = Yahns.now
-    (now - @last_expire) >= 1.0 or return # don't expire too frequently
+    (now - @last_expire) >= 1.0 or return @count # don't expire too frequently
 
     # @fdmap_ary may be huge, so always expire a bunch at once to
     # avoid getting to this method too frequently
@@ -104,8 +104,11 @@ class Yahns::Fdmap # :nodoc:
     end
 
     @last_expire = Yahns.now
-    msg = timeout ? "timeout=#{timeout}" : "client_timeout"
-    @logger.info("dropping #{nr} of #@count clients for #{msg}")
+    if nr != 0
+      msg = timeout ? "timeout=#{timeout}" : "client_timeout"
+      @logger.info("dropping #{nr} of #@count clients for #{msg}")
+    end
+    @count
   end
 
   # used for graceful shutdown
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index ba2066b..00e5f15 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -496,7 +496,8 @@ class Yahns::Server # :nodoc:
   def dropping(fdmap)
     if drop_acceptors[0] || fdmap.size > 0
       timeout = @shutdown_expire < Yahns.now ? -1 : @shutdown_timeout
-      fdmap.desperate_expire(timeout)
+      n = fdmap.desperate_expire(timeout)
+      $0 = "yahns quitting, #{n} FD(s) remain"
       true
     else
       false
diff --git a/lib/yahns/server_mp.rb b/lib/yahns/server_mp.rb
index fa12a0c..c9cd207 100644
--- a/lib/yahns/server_mp.rb
+++ b/lib/yahns/server_mp.rb
@@ -159,7 +159,7 @@ module Yahns::ServerMP # :nodoc:
   def mp_sig_handle(watch, alive)
     # not performance critical
     watch.delete_if { |io| io.to_io.closed? }
-    if r = IO.select(watch, nil, nil, alive ? nil : 0.01)
+    if r = IO.select(watch, nil, nil, alive ? nil : 0.1)
       r[0].each(&:yahns_step)
     end
     case @sig_queue.shift
diff --git a/test/test_server.rb b/test/test_server.rb
index 9f33b42..c6d70cb 100644
--- a/test/test_server.rb
+++ b/test/test_server.rb
@@ -725,6 +725,41 @@ class TestServer < Testcase
     assert_nil c.read(666)
   end
 
+  def test_slow_shutdown_timeout; _slow_shutdown(nil); end
+  def test_slow_shutdown_timeout_mp; _slow_shutdown(1); end
+
+  def _slow_shutdown(nr_workers)
+    err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
+    pid = mkserver(cfg) do
+      ru = lambda { |e| [ 200, {'Content-Length'=>'2'}, %w(OK) ] }
+      cfg.instance_eval do
+        app(:rack, ru) { listen "#{host}:#{port}" }
+        stderr_path err.path
+        worker_processes(nr_workers) if nr_workers
+      end
+    end
+    c = get_tcp_client(host, port)
+    c.write 'G'
+    100000.times { Thread.pass }
+    Process.kill(:QUIT, pid)
+    "ET / HTTP/1.1\r\nHost: example.com\r\n\r\n".each_byte do |x|
+      Thread.pass
+      c.write(x.chr)
+      Thread.pass
+    end
+    assert_equal c, c.wait(30)
+    buf = ''.dup
+    re = /\r\n\r\nOK\z/
+    Timeout.timeout(30) do
+      begin
+        buf << c.readpartial(666)
+      end until re =~ buf
+    end
+    c.close
+    _, status = Timeout.timeout(5) { Process.waitpid2(pid) }
+    assert status.success?, status.inspect
+  end
+
   def test_before_exec
     err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
     ru = lambda { |e| [ 200, {'Content-Length'=>'2' }, %w(OK) ] }