about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-10-11 20:42:21 -0700
committerEric Wong <normalperson@yhbt.net>2009-10-11 20:53:19 -0700
commit90a03ee550741465ea43fd70e087851e17246fb6 (patch)
treeaac5c0422e3ab17d652d96bc2cafd83fef5a8a23
parentdf204a05d3a5bda8f716fa9f51be464fa59a3af1 (diff)
downloadrainbows-90a03ee550741465ea43fd70e087851e17246fb6.tar.gz
-rw-r--r--lib/rainbows/revactor.rb16
-rw-r--r--t/sleep.ru11
-rwxr-xr-xt/t3002-revactor-graceful.sh38
3 files changed, 60 insertions, 5 deletions
diff --git a/lib/rainbows/revactor.rb b/lib/rainbows/revactor.rb
index e1c52e3..fb35394 100644
--- a/lib/rainbows/revactor.rb
+++ b/lib/rainbows/revactor.rb
@@ -94,7 +94,7 @@ module Rainbows
               Actor.receive { |filter| filter.when(:resume) {} }
             end
             actor = Actor.spawn(l.accept) { |c| process_client(c) }
-            clients[actor.object_id] = false
+            clients[actor.object_id] = actor
             root.link(actor)
           rescue Errno::EAGAIN, Errno::ECONNABORTED
           rescue Errno::EBADF
@@ -106,18 +106,24 @@ module Rainbows
       end
 
       m = 0
-      begin
+      check_quit = lambda do
         worker.tmp.chmod(m = 0 == m ? 1 : 0)
-        if listeners.any? { |l| l.dead? } || master_pid != Process.ppid
+        if listeners.any? { |l| l.dead? } ||
+           master_pid != Process.ppid ||
+           LISTENERS.first.nil?
           alive = false
-          clients.each_pair { |a,_| a[:quit] = true }
+          clients.each_value { |a| a[:quit] = true }
         end
+      end
+
+      begin
         Actor.receive do |filter|
-          filter.after(timeout) { redo }
+          filter.after(timeout, &check_quit)
           filter.when(Case[:exit, Actor, Object]) do |_,actor,_|
             orig = clients.size
             clients.delete(actor.object_id)
             orig >= limit and listeners.each { |l| l << :resume }
+            check_quit.call
           end
         end
       end while alive || clients.size > 0
diff --git a/t/sleep.ru b/t/sleep.ru
new file mode 100644
index 0000000..66b29af
--- /dev/null
+++ b/t/sleep.ru
@@ -0,0 +1,11 @@
+use Rack::ContentLength
+use Rack::ContentType
+sleep_class = ENV['SLEEP_CLASS']
+sleep_class = sleep_class ? Object.const_get(sleep_class) : Kernel
+$stderr.puts "sleep_class=#{sleep_class.inspect}"
+run lambda { |env|
+  nr = 1
+  env["PATH_INFO"] =~ %r{/([\d\.]+)\z} and nr = $1.to_f
+  sleep_class.sleep(nr)
+  [ 200, {}, [ "Hello\n" ] ]
+}
diff --git a/t/t3002-revactor-graceful.sh b/t/t3002-revactor-graceful.sh
new file mode 100755
index 0000000..b1512b9
--- /dev/null
+++ b/t/t3002-revactor-graceful.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+. ./test-lib.sh
+require_revactor
+
+eval $(unused_listen)
+rtmpfiles unicorn_config curl_out curl_err pid r_err r_out
+nr_actor=10
+nr_client=10
+cat > $unicorn_config <<EOF
+listen "$listen"
+stderr_path "$r_err"
+stdout_path "$r_out"
+pid "$pid"
+Rainbows! do
+  use :Revactor
+  worker_connections $nr_actor
+end
+EOF
+
+SLEEP_CLASS=Actor rainbows -D sleep.ru -c $unicorn_config
+wait_for_pid $pid
+
+for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
+do
+        curl -sSf http://$listen/5 >> $curl_out 2>> $curl_err &
+done
+sleep 2
+kill -QUIT $(cat $pid)
+wait
+
+dbgcat r_err
+! test -s $curl_err
+test x"$(wc -l < $curl_out)" = x$nr_client
+nr=$(sort < $curl_out | uniq | wc -l)
+
+test "$nr" -eq 1
+test x$(sort < $curl_out | uniq) = xHello
+grep -v Error $r_err