diff options
Diffstat (limited to 'lib/rainbows/rev/thread.rb')
-rw-r--r-- | lib/rainbows/rev/thread.rb | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/rainbows/rev/thread.rb b/lib/rainbows/rev/thread.rb new file mode 100644 index 0000000..8fa43ac --- /dev/null +++ b/lib/rainbows/rev/thread.rb @@ -0,0 +1,53 @@ +# -*- encoding: binary -*- +require 'thread' +require 'rainbows/rev/master' + +module Rainbows + module Rev + + class ThreadClient < Client + + def app_call + KATO.delete(self) + disable + @env[RACK_INPUT] = @input + @input = nil # not sure why, @input seems to get closed otherwise... + app_dispatch # must be implemented by subclass + end + + # this is only called in the master thread + def response_write(response) + enable + alive = @hp.keepalive? && G.alive + out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers? + DeferredResponse.write(self, response, out) + return quit unless alive && G.alive + + @env.clear + @hp.reset + @state = :headers + # keepalive requests are always body-less, so @input is unchanged + if @hp.headers(@env, @buf) + @input = HttpRequest::NULL_IO + app_call + else + KATO[self] = Time.now + end + end + + # fails-safe application dispatch, we absolutely cannot + # afford to fail or raise an exception (killing the thread) + # here because that could cause a deadlock and we'd leak FDs + def app_response + begin + @env[REMOTE_ADDR] = @remote_addr + APP.call(@env.update(RACK_DEFAULTS)) + rescue => e + Error.app(e) # we guarantee this does not raise + [ 500, {}, [] ] + end + end + + end + end +end |