about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-01-11 16:01:20 -0800
committerEric Wong <normalperson@yhbt.net>2011-01-11 16:28:44 -0800
commit89f948aeaef34114ec61291ff8ffbebcf85a748e (patch)
tree6c0a8d3a7b7b6f9d33ee2f3498b3d55acfda1343
parent0515dee246536cb3942f51f8d264737f106d3985 (diff)
downloadrainbows-89f948aeaef34114ec61291ff8ffbebcf85a748e.tar.gz
We cannot trigger on_read events and invoke the HTTP parser and
modify @env while we're waiting for an application to run
async.callback.  We also need to clear (and *maybe* re-set)
@deferred if we're writing from async.callback
-rw-r--r--lib/rainbows/coolio/client.rb7
-rw-r--r--lib/rainbows/ev_core.rb1
-rw-r--r--lib/rainbows/event_machine/client.rb2
-rw-r--r--t/t0402-async-keepalive.sh22
4 files changed, 24 insertions, 8 deletions
diff --git a/lib/rainbows/coolio/client.rb b/lib/rainbows/coolio/client.rb
index 6264df7..f44d2aa 100644
--- a/lib/rainbows/coolio/client.rb
+++ b/lib/rainbows/coolio/client.rb
@@ -105,17 +105,12 @@ class Rainbows::Coolio::Client < Coolio::IO
     @state = :headers
   end
 
-  def coolio_write_async_response(response)
-    write_async_response(response)
-    @deferred = nil
-  end
-
   def app_call
     KATO.delete(self)
     disable if enabled?
     @env[RACK_INPUT] = @input
     @env[REMOTE_ADDR] = @_io.kgio_addr
-    @env[ASYNC_CALLBACK] = method(:coolio_write_async_response)
+    @env[ASYNC_CALLBACK] = method(:write_async_response)
     status, headers, body = catch(:async) {
       APP.call(@env.merge!(RACK_DEFAULTS))
     }
diff --git a/lib/rainbows/ev_core.rb b/lib/rainbows/ev_core.rb
index 0bdaab3..a3bf50f 100644
--- a/lib/rainbows/ev_core.rb
+++ b/lib/rainbows/ev_core.rb
@@ -22,6 +22,7 @@ module Rainbows::EvCore
       alive = headers.include?(Content_Length) ||
               !!(%r{\Achunked\z}i =~ headers[Transfer_Encoding])
     end
+    @deferred = nil
     ev_write_response(status, headers, body, alive)
   end
 
diff --git a/lib/rainbows/event_machine/client.rb b/lib/rainbows/event_machine/client.rb
index c9f63a4..b75d7ee 100644
--- a/lib/rainbows/event_machine/client.rb
+++ b/lib/rainbows/event_machine/client.rb
@@ -40,7 +40,7 @@ class Rainbows::EventMachine::Client < EM::Connection
       APP.call(@env.merge!(RACK_DEFAULTS))
     }
 
-    (nil == status || -1 == status) or
+    (nil == status || -1 == status) ? @deferred = true :
       ev_write_response(status, headers, body, @hp.next?)
   end
 
diff --git a/t/t0402-async-keepalive.sh b/t/t0402-async-keepalive.sh
index fdf4cbc..7b7b2e7 100644
--- a/t/t0402-async-keepalive.sh
+++ b/t/t0402-async-keepalive.sh
@@ -9,7 +9,7 @@ Coolio|NeverBlock|EventMachine) ;;
         ;;
 esac
 
-t_plan 11 "async_chunk_app test for test for $model"
+t_plan 12 "async_chunk_app test for test for $model"
 
 CONFIG_RU=async_chunk_app.ru
 
@@ -44,6 +44,26 @@ t_begin "async.callback supports pipelining" && {
         test 3 -eq "$(grep 'World ' $tmp | wc -l)"
 }
 
+t_begin "async.callback supports delayed pipelining" && {
+        rm -f $tmp
+        t0=$(date +%s)
+        (
+                cat $fifo > $tmp &
+                printf 'GET /0 HTTP/1.1\r\nHost: example.com\r\n\r\n'
+                sleep 1
+                printf 'GET /1 HTTP/1.1\r\nHost: example.com\r\n\r\n'
+                sleep 1
+                printf 'GET /2 HTTP/1.0\r\nHost: example.com\r\n\r\n'
+                wait
+        ) | socat - TCP:$listen > $fifo
+        t1=$(date +%s)
+        elapsed=$(( $t1 - $t0 ))
+        t_info "elapsed=$elapsed $model.$0 ($t_current)"
+        test 3 -eq "$(fgrep 'HTTP/1.1 200 OK' $tmp | wc -l)"
+        test 3 -eq "$(grep '^Hello ' $tmp | wc -l)"
+        test 3 -eq "$(grep 'World ' $tmp | wc -l)"
+}
+
 t_begin "async.callback supports pipelining with delay $DELAY" && {
         rm -f $tmp
         t0=$(date +%s)