From ac05e7035e1946b78ce4679548db7680aa01734c Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 17 Aug 2010 08:35:03 +0000 Subject: avoid EBADF with certain middlewares when proxying First off we use an FD_MAP to avoid creating redundant IO objects which map to the same FD. When that doesn't work, we'll fall back to trapping Errno::EBADF and IOError where appropriate. --- lib/rainbows/dev_fd_response.rb | 4 +++- lib/rainbows/response/body.rb | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/rainbows') diff --git a/lib/rainbows/dev_fd_response.rb b/lib/rainbows/dev_fd_response.rb index 637bcc2..7f70b8e 100644 --- a/lib/rainbows/dev_fd_response.rb +++ b/lib/rainbows/dev_fd_response.rb @@ -14,7 +14,8 @@ class Rainbows::DevFdResponse < Struct.new(:app) # :stopdoc: - # + FD_MAP = Rainbows::FD_MAP + # make this a no-op under Rubinius, it's pointless anyways # since Rubinius doesn't have IO.copy_stream def self.new(app) @@ -37,6 +38,7 @@ class Rainbows::DevFdResponse < Struct.new(:app) headers = HeaderHash.new(headers) st = io.stat fileno = io.fileno + FD_MAP[fileno] = io if st.file? headers['Content-Length'] ||= st.size.to_s headers.delete('Transfer-Encoding') diff --git a/lib/rainbows/response/body.rb b/lib/rainbows/response/body.rb index cf14f08..2535374 100644 --- a/lib/rainbows/response/body.rb +++ b/lib/rainbows/response/body.rb @@ -30,6 +30,12 @@ module Rainbows::Response::Body # :nodoc: ALIASES = {} + FD_MAP = Rainbows::FD_MAP + + def io_for_fd(fd) + FD_MAP.delete(fd) || IO.new(fd) + end + # to_io is not part of the Rack spec, but make an exception here # since we can conserve path lookups and file descriptors. # \Rainbows! will never get here without checking for the existence @@ -41,7 +47,7 @@ module Rainbows::Response::Body # :nodoc: # try to take advantage of Rainbows::DevFdResponse, calling File.open # is a last resort path = body.to_path - path =~ %r{\A/dev/fd/(\d+)\z} ? IO.new($1.to_i) : File.open(path) + path =~ %r{\A/dev/fd/(\d+)\z} ? io_for_fd($1.to_i) : File.open(path) end end -- cgit v1.2.3-24-ge0c7