diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-10-18 18:27:28 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-10-18 18:27:28 +0000 |
commit | 2c5b5bb7a3bab2d6cacfa251afbef04f048472c2 (patch) | |
tree | 57b42e9f6699bdb7609c47d8707f271bea4df80e | |
parent | 3555fdce0c9cf9bb6860a79fdc6843a1e96c9888 (diff) | |
download | yahns-2c5b5bb7a3bab2d6cacfa251afbef04f048472c2.tar.gz |
We want to shutdown gracefully, but still relatively quickly (to make way for the new one). So we must disable persistent connections to prevent clients from keeping to-be-dead server alive indefinitely.
-rw-r--r-- | lib/yahns/config.rb | 4 | ||||
-rw-r--r-- | lib/yahns/server.rb | 14 | ||||
-rw-r--r-- | lib/yahns/server_mp.rb | 9 | ||||
-rw-r--r-- | test/test_server.rb | 10 |
4 files changed, 25 insertions, 12 deletions
diff --git a/lib/yahns/config.rb b/lib/yahns/config.rb index d38c090..4861f3e 100644 --- a/lib/yahns/config.rb +++ b/lib/yahns/config.rb @@ -29,6 +29,10 @@ class Yahns::Config # :nodoc: raise ArgumentError, msg end + def postfork_cleanup + @app_ctx = @set = @qeggs = @app_instances = @config_file = nil + end + def config_reload! #:nodoc: # app_instance:app_ctx is a 1:N relationship @config_listeners = {} # name/address -> options diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb index c7a5a57..e8f1213 100644 --- a/lib/yahns/server.rb +++ b/lib/yahns/server.rb @@ -292,14 +292,22 @@ class Yahns::Server # :nodoc: @logger.info "#{prefix}done reopening logs" end + def quit_enter(alive) + self.listeners = [] + exit(0) unless alive # drop connections immediately if signaled twice + @config.config_listeners.each_value do |opts| + ctx = opts[:yahns_app_ctx] or next + ctx.persistent_connections = false # Yahns::HttpContext + end + false + end + def sp_sig_handle(alive) @sev.kgio_wait_readable(alive ? nil : 0.01) @sev.yahns_step case sig = @sig_queue.shift when :QUIT, :TERM, :INT - self.listeners = [] # stop accepting new connections - exit(0) unless alive - return false + return quit_enter(alive) when :USR1 usr1_reopen('') when :USR2 diff --git a/lib/yahns/server_mp.rb b/lib/yahns/server_mp.rb index 8818bac..c75a3c9 100644 --- a/lib/yahns/server_mp.rb +++ b/lib/yahns/server_mp.rb @@ -151,7 +151,7 @@ module Yahns::ServerMP # :nodoc: def fdmap_init_mp fdmap = fdmap_init # builds apps (if not preloading) EXIT_SIGS.each { |sig| trap(sig) { sqwakeup(sig) } } - @config = nil + @config.postfork_cleanup # reduce live objects fdmap end @@ -170,12 +170,9 @@ module Yahns::ServerMP # :nodoc: # not performance critical r = IO.select([worker, @sev], nil, nil, alive ? nil : 0.01) and r[0].each { |io| io.yahns_step } - case sig = @sig_queue.shift + case @sig_queue.shift when *EXIT_SIGS - self.listeners = [] - exit(0) unless alive # drop connections immediately if signaled twice - @logger.info("received SIG#{sig}, gracefully exiting") - return false + return quit_enter(alive) when :USR1 usr1_reopen("worker ") end diff --git a/test/test_server.rb b/test/test_server.rb index 289770d..88dd3fb 100644 --- a/test/test_server.rb +++ b/test/test_server.rb @@ -50,12 +50,16 @@ class TestServer < Testcase buf << c.readpartial(4096) end end + Process.kill(:QUIT, pid) + "GET / HTTP/1.1\r\n\r\n".each_byte { |x| Thread.pass; c.write(x.chr) } + buf = Timeout.timeout(10) { c.read } + assert_match(/Connection: close/, buf) + _, status = Timeout.timeout(10) { Process.waitpid2(pid) } + assert status.success?, status.inspect + c.close rescue => e Yahns::Log.exception(Logger.new($stderr), "test", e) raise - ensure - c.close if c - quit_wait(pid) end def test_input_body_true; input_body(true); end |