about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/yahns/config.rb7
-rw-r--r--lib/yahns/server_mp.rb10
-rw-r--r--test/test_server.rb45
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"