Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix timeout regression #320

Merged
merged 2 commits into from
Mar 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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