From 052e2b3608071d9cd9d6b1d12f8cb69ac29124af Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 25 Jul 2010 09:28:22 +0000 Subject: rev*: properly handle pipelined responses w/sendfile With sendfile enabled, we must avoid writing headers (or normal, non-file responses) while a file is deferred for sending. This means we must disable processing of new requests while a file is deferred for sending and use the on_write_complete callback less aggressively. --- t/t0024-pipelined-sendfile-response.sh | 67 ++++++++++++++++++++++++++++++++++ t/test_isolate.rb | 1 + 2 files changed, 68 insertions(+) create mode 100755 t/t0024-pipelined-sendfile-response.sh (limited to 't') diff --git a/t/t0024-pipelined-sendfile-response.sh b/t/t0024-pipelined-sendfile-response.sh new file mode 100755 index 0000000..2acc243 --- /dev/null +++ b/t/t0024-pipelined-sendfile-response.sh @@ -0,0 +1,67 @@ +#!/bin/sh +. ./test-lib.sh + +case $model in +EventMachine|NeverBlock) + t_info "skipping $T since it's not compatible with $model" + exit 0 + ;; +*) ;; +esac + +t_plan 5 "pipelined sendfile response for $model" + +t_begin "setup and startup" && { + rtmpfiles err out + rainbows_setup $model + echo 'require "sendfile"' >> $unicorn_config + echo 'def (::IO).copy_stream(*x); abort "NO"; end' >> $unicorn_config + + # can't load Rack::Lint here since it clobbers body#to_path + rainbows -E none -D large-file-response.ru -c $unicorn_config + rainbows_wait_start +} + +t_begin "read random blob sha1" && { + random_blob_sha1=$(rsha1 < random_blob) +} + +script=' +require "digest/sha1" +require "kcar" +$stdin.binmode +expect = ENV["random_blob_sha1"] +kcar = Kcar::Response.new($stdin, {}) +3.times do + nr = 0 + status, headers, body = kcar.rack + dig = Digest::SHA1.new + body.each { |buf| dig << buf ; nr += buf.size } + sha1 = dig.hexdigest + sha1 == expect or abort "mismatch: sha1=#{sha1} != expect=#{expect}" + body.close +end +$stdout.syswrite("ok\n") +' + +t_begin "pipeline 3 HTTP requests" && { + req='GET /random_blob HTTP/1.1\r\nHost: example.com\r\n' + req="$req"'\r\n'"$req"'\r\n'"$req" + req="$req"'Connection: close\r\n\r\n' + ( + export random_blob_sha1 + $RUBY -e "$script" < $fifo >> $ok & + printf "$req" + wait + echo ok >> $ok + ) | socat - TCP:$listen > $fifo + test 2 -eq $(grep '^ok$' $ok |wc -l) +} + +t_begin "shutdown server" && { + kill -QUIT $rainbows_pid +} + +t_begin "check stderr" && check_stderr + +t_done diff --git a/t/test_isolate.rb b/t/test_isolate.rb index f4b4b77..fb911af 100644 --- a/t/test_isolate.rb +++ b/t/test_isolate.rb @@ -16,6 +16,7 @@ $stdout.reopen($stderr) Isolate.now!(opts) do gem 'rack', '1.1.0' # Cramp currently requires ~> 1.1.0 gem 'unicorn', '1.1.1' + gem 'kcar', '0.1.1' if engine == "ruby" gem 'sendfile', '1.0.0' # next Rubinius should support this -- cgit v1.2.3-24-ge0c7