diff options
-rw-r--r-- | lib/rainbows/revactor.rb | 16 | ||||
-rw-r--r-- | t/sleep.ru | 11 | ||||
-rwxr-xr-x | t/t3002-revactor-graceful.sh | 38 |
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 |