diff options
-rw-r--r-- | lib/yahns/config.rb | 7 | ||||
-rw-r--r-- | lib/yahns/server_mp.rb | 10 | ||||
-rw-r--r-- | test/test_server.rb | 45 |
3 files changed, 53 insertions, 9 deletions
diff --git a/lib/yahns/config.rb b/lib/yahns/config.rb index 873722d..a46868b 100644 --- a/lib/yahns/config.rb +++ b/lib/yahns/config.rb @@ -103,13 +103,8 @@ class Yahns::Config # :nodoc: end def _add_hook(var, my_proc) - case my_proc - when Proc - my_proc.arity == 0 or raise ArgumentError, - "#{var}=#{my_proc.inspect} should not take arguments" - else + Proc === my_proc or raise ArgumentError, "invalid type: #{var}=#{my_proc.inspect}" - end # this sets: # :atfork_prepare, :atfork_parent, :atfork_child diff --git a/lib/yahns/server_mp.rb b/lib/yahns/server_mp.rb index 8272a9e..1e2f1c8 100644 --- a/lib/yahns/server_mp.rb +++ b/lib/yahns/server_mp.rb @@ -48,21 +48,25 @@ module Yahns::ServerMP # :nodoc: @sev = Yahns::Sigevent.new switch_user(*@user) if @user @user = @workers = nil - @atfork_child.each(&:call) if @atfork_child + __call_hooks(@atfork_child, worker.nr) @atfork_child = @atfork_parent = @atfork_prepare = nil end + def __call_hooks(ary, worker_nr) + ary.each { |x| x.call(worker_nr) } if ary + end + def spawn_missing_workers worker_nr = -1 until (worker_nr += 1) == @worker_processes @workers.value?(worker_nr) and next worker = Yahns::Worker.new(worker_nr) @logger.info("worker=#{worker_nr} spawning...") - @atfork_prepare.each(&:call) if @atfork_parent + __call_hooks(@atfork_prepare, worker_nr) if pid = fork @workers[pid] = worker.atfork_parent # XXX is this useful? - @atfork_parent.each(&:call) if @atfork_parent + __call_hooks(@atfork_parent, worker_nr) else worker_atfork_internal(worker) run_mp_worker(worker) diff --git a/test/test_server.rb b/test/test_server.rb index 6059e03..e6ddefc 100644 --- a/test/test_server.rb +++ b/test/test_server.rb @@ -440,6 +440,51 @@ class TestServer < Testcase quit_wait(pid) end + def test_mp_hooks_worker_nr + err = @err + out = tmpfile(%w(mp_hooks .out)) + cfg = Yahns::Config.new + host, port = @srv.addr[3], @srv.addr[1] + cfg.instance_eval do + ru = lambda {|_|x="#$$";[200,{'Content-Length'=>x.size.to_s },[x]]} + GTL.synchronize { + app(:rack, ru) { + listen "#{host}:#{port}" + persistent_connections false + } + worker_processes(1) do + atfork_child { |nr| puts "af.#{nr} #$$ worker is running" } + atfork_prepare { |nr| puts "af.#{nr} #$$ parent about to spawn" } + atfork_parent { |nr| puts "af.#{nr} #$$ this is probably not useful" } + end + } + stderr_path err.path + stdout_path out.path + end + pid = mkserver(cfg) + c = get_tcp_client(host, port) + c.write("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n") + buf = Timeout.timeout(10) { c.read } + c.close + head, body = buf.split(/\r\n\r\n/) + assert_match(/200 OK/, head) + assert_match(/\A\d+\z/, body) + worker_pid = body.to_i + lines = out.readlines.map!(&:chomp!) + out.close! + + assert_equal 3, lines.size + assert_equal("af.0 #{pid} parent about to spawn", lines.shift) + + # child/parent ordering is not guaranteed + assert_equal 1, + lines.grep(/\Aaf\.0 #{pid} this is probably not useful\z/).size + assert_equal 1, + lines.grep(/\Aaf\.0 #{worker_pid} worker is running\z/).size + ensure + quit_wait(pid) + end + def test_pidfile_usr2 tmpdir = Dir.mktmpdir pidf = "#{tmpdir}/pid" |