Skip to content

Commit

Permalink
Merge pull request #320 from httprb/tarcieri/fix-timeout-regression
Browse files Browse the repository at this point in the history
Fix timeout regression
  • Loading branch information
tarcieri committed Mar 19, 2016
2 parents f7e028a + d324605 commit 979cee5
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 71 deletions.
40 changes: 12 additions & 28 deletions lib/http/timeout/global.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ def connect_ssl
reset_timer

begin
@socket.connect_nonblock
socket.connect_nonblock
rescue IO::WaitReadable
IO.select([@socket], nil, nil, time_left)
IO.select([socket], nil, nil, time_left)
log_time
retry
rescue IO::WaitWritable
IO.select(nil, [@socket], nil, time_left)
IO.select(nil, [socket], nil, time_left)
log_time
retry
end
Expand Down Expand Up @@ -104,32 +104,16 @@ def perform_io
:eof
end

if RUBY_VERSION < "2.0.0"
# Wait for a socket to become readable
def wait_readable_or_timeout
IO.select([@socket], nil, nil, time_left)
log_time
end

# Wait for a socket to become writable
def wait_writable_or_timeout
IO.select(nil, [@socket], nil, time_left)
log_time
end
else
require "io/wait"

# Wait for a socket to become readable
def wait_readable_or_timeout
@socket.to_io.wait_readable(time_left)
log_time
end
# Wait for a socket to become readable
def wait_readable_or_timeout
IO.select([@socket], nil, nil, time_left)
log_time
end

# Wait for a socket to become writable
def wait_writable_or_timeout
@socket.to_io.wait_writable(time_left)
log_time
end
# Wait for a socket to become writable
def wait_writable_or_timeout
IO.select(nil, [@socket], nil, time_left)
log_time
end

# Due to the run/retry nature of nonblocking I/O, it's easier to keep track of time
Expand Down
49 changes: 13 additions & 36 deletions lib/http/timeout/null.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,45 +50,22 @@ def write(data)
end
alias << write

# These cops can be re-eanbled after we go Ruby 2.0+ only
# rubocop:disable Lint/UselessAccessModifier, Metrics/BlockNesting

private

if RUBY_VERSION < "2.0.0"
# Retry reading
def rescue_readable
yield
rescue IO::WaitReadable
retry if IO.select([@socket], nil, nil, read_timeout)
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
end

# Retry writing
def rescue_writable
yield
rescue IO::WaitWritable
retry if IO.select(nil, [@socket], nil, write_timeout)
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
end
else
require "io/wait"

# Retry reading
def rescue_readable
yield
rescue IO::WaitReadable
retry if @socket.to_io.wait_readable(read_timeout)
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
end
# Retry reading
def rescue_readable
yield
rescue IO::WaitReadable
retry if IO.select([socket], nil, nil, read_timeout)
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
end

# Retry writing
def rescue_writable
yield
rescue IO::WaitWritable
retry if @socket.to_io.wait_writable(write_timeout)
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
end
# Retry writing
def rescue_writable
yield
rescue IO::WaitWritable
retry if IO.select(nil, [socket], nil, write_timeout)
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
end
end
end
Expand Down
14 changes: 7 additions & 7 deletions lib/http/timeout/per_operation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def connect_ssl
# Read data from the socket
def readpartial(size)
rescue_readable do
@socket.read_nonblock(size)
socket.read_nonblock(size)
end
rescue EOFError
:eof
Expand All @@ -48,7 +48,7 @@ def readpartial(size)
# Write data to the socket
def write(data)
rescue_writable do
@socket.write_nonblock(data)
socket.write_nonblock(data)
end
rescue EOFError
:eof
Expand All @@ -59,14 +59,14 @@ def write(data)
# Read data from the socket
def readpartial(size)
loop do
result = @socket.read_nonblock(size, :exception => false)
result = socket.read_nonblock(size, :exception => false)
if result.nil?
return :eof
elsif result != :wait_readable
return result
end

unless @socket.to_io.wait_readable(read_timeout)
unless IO.select([socket], nil, nil, read_timeout)
fail TimeoutError, "Read timed out after #{read_timeout} seconds"
end
end
Expand All @@ -75,11 +75,11 @@ def readpartial(size)
# Write data to the socket
def write(data)
loop do
result = @socket.write_nonblock(data, :exception => false)
result = socket.write_nonblock(data, :exception => false)
return result unless result == :wait_writable

unless @socket.to_io.wait_writable(write_timeout)
fail TimeoutError, "Write timed out after #{write_timeout} seconds"
unless IO.select(nil, [socket], nil, write_timeout)
fail TimeoutError, "Read timed out after #{write_timeout} seconds"
end
end
end
Expand Down

0 comments on commit 979cee5

Please sign in to comment.