Skip to content

Commit

Permalink
Merge pull request #283 from httprb/tarcieri/io-wait
Browse files Browse the repository at this point in the history
Use io/wait on platforms where it's available
  • Loading branch information
tarcieri committed Dec 26, 2015
2 parents 6f4a06b + f4df840 commit 6fa029b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
AllCops:
DisplayCopNames: true

Metrics/BlockNesting:
Max: 2

Expand Down
34 changes: 25 additions & 9 deletions lib/http/timeout/global.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,32 @@ def perform_io
:eof
end

# Wait for a socket to become readable
def wait_readable_or_timeout
IO.select([@socket], nil, nil, time_left)
log_time
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
# 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 writable
def wait_writable_or_timeout
@socket.to_io.wait_writable(time_left)
log_time
end
end

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

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

private

# Retry reading
def rescue_readable
yield
rescue IO::WaitReadable
if IO.select([socket], nil, nil, read_timeout)
retry
else
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
end

# Retry writing
def rescue_writable
yield
rescue IO::WaitWritable
if IO.select(nil, [socket], nil, write_timeout)
retry
else
# 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
end
Expand Down
14 changes: 10 additions & 4 deletions lib/http/timeout/per_operation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,17 @@ def write(data)
# Read data from the socket
def readpartial(size)
loop do
result = socket.read_nonblock(size, :exception => false)
result = rescue_readable do
socket.read_nonblock(size, :exception => false)
end

if result.nil?
return :eof
elsif result != :wait_readable
return result
end

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

return result unless result == :wait_writable

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

0 comments on commit 6fa029b

Please sign in to comment.