diff options
-rw-r--r-- | lib/unicorn/http_request.rb | 38 | ||||
-rw-r--r-- | test/unit/test_ccc.rb | 11 |
2 files changed, 39 insertions, 10 deletions
diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb index 9010007..7253497 100644 --- a/lib/unicorn/http_request.rb +++ b/lib/unicorn/http_request.rb @@ -105,7 +105,7 @@ class Unicorn::HttpParser env.include?('rack.hijack_io'.freeze) end - if defined?(Raindrops::TCP_Info) + if Raindrops.const_defined?(:TCP_Info) TCPI = Raindrops::TCP_Info.allocate def check_client_connection(socket) # :nodoc: @@ -118,14 +118,34 @@ class Unicorn::HttpParser end end - def closed_state?(state) # :nodoc: - case state - when 1 # ESTABLISHED - false - when 8, 6, 7, 9, 11 # CLOSE_WAIT, TIME_WAIT, CLOSE, LAST_ACK, CLOSING - true - else - false + if Raindrops.const_defined?(:TCP) + # raindrops 0.18.0+ supports FreeBSD + Linux using the same names + # Evaluate these hash lookups at load time so we can + # generate an opt_case_dispatch instruction + eval <<-EOS + def closed_state?(state) # :nodoc: + case state + when #{Raindrops::TCP[:ESTABLISHED]} + false + when #{Raindrops::TCP.values_at( + :CLOSE_WAIT, :TIME_WAIT, :CLOSE, :LAST_ACK, :CLOSING).join(',')} + true + else + false + end + end + EOS + else + # raindrops before 0.18 only supported TCP_INFO under Linux + def closed_state?(state) # :nodoc: + case state + when 1 # ESTABLISHED + false + when 8, 6, 7, 9, 11 # CLOSE_WAIT, TIME_WAIT, CLOSE, LAST_ACK, CLOSING + true + else + false + end end end else diff --git a/test/unit/test_ccc.rb b/test/unit/test_ccc.rb index 22b1a9c..0db0c38 100644 --- a/test/unit/test_ccc.rb +++ b/test/unit/test_ccc.rb @@ -12,7 +12,9 @@ class TestCccTCPI < Test::Unit::TestCase port = srv.addr[1] err = Tempfile.new('unicorn_ccc') rd, wr = IO.pipe + sleep_pipe = IO.pipe pid = fork do + sleep_pipe[1].close reqs = 0 rd.close worker_pid = nil @@ -22,7 +24,10 @@ class TestCccTCPI < Test::Unit::TestCase $$ end reqs += 1 - sleep(1) if env['PATH_INFO'] == '/sleep' + + # will wake up when writer closes + sleep_pipe[0].read if env['PATH_INFO'] == '/sleep' + [ 200, [ %w(Content-Length 0), %w(Content-Type text/plain) ], [] ] end ENV['UNICORN_FD'] = srv.fileno.to_s @@ -57,6 +62,10 @@ class TestCccTCPI < Test::Unit::TestCase "Host: example.com\r\n\r\n") client.close end + sleep_pipe[1].close # wake up the reader in the worker + res = sleeper.read + assert_match %r{\AHTTP/1\.1 200}, res, 'got part of first sleeper response' + assert_match %r{\r\n\r\n\z}, res, 'got end of sleeper response' sleeper.close kpid = pid pid = nil |