Skip to content

Commit 6fa029b

Browse files
committed
Merge pull request #283 from httprb/tarcieri/io-wait
Use io/wait on platforms where it's available
2 parents 6f4a06b + f4df840 commit 6fa029b

File tree

4 files changed

+70
-28
lines changed

4 files changed

+70
-28
lines changed

.rubocop.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
AllCops:
2+
DisplayCopNames: true
3+
14
Metrics/BlockNesting:
25
Max: 2
36

lib/http/timeout/global.rb

+25-9
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,32 @@ def perform_io
104104
:eof
105105
end
106106

107-
# Wait for a socket to become readable
108-
def wait_readable_or_timeout
109-
IO.select([@socket], nil, nil, time_left)
110-
log_time
111-
end
107+
if RUBY_VERSION < "2.0.0"
108+
# Wait for a socket to become readable
109+
def wait_readable_or_timeout
110+
IO.select([@socket], nil, nil, time_left)
111+
log_time
112+
end
112113

113-
# Wait for a socket to become writable
114-
def wait_writable_or_timeout
115-
IO.select(nil, [@socket], nil, time_left)
116-
log_time
114+
# Wait for a socket to become writable
115+
def wait_writable_or_timeout
116+
IO.select(nil, [@socket], nil, time_left)
117+
log_time
118+
end
119+
else
120+
require "io/wait"
121+
122+
# Wait for a socket to become readable
123+
def wait_readable_or_timeout
124+
@socket.to_io.wait_readable(time_left)
125+
log_time
126+
end
127+
128+
# Wait for a socket to become writable
129+
def wait_writable_or_timeout
130+
@socket.to_io.wait_writable(time_left)
131+
log_time
132+
end
117133
end
118134

119135
# Due to the run/retry nature of nonblocking I/O, it's easier to keep track of time

lib/http/timeout/null.rb

+32-15
Original file line numberDiff line numberDiff line change
@@ -50,26 +50,43 @@ def write(data)
5050
end
5151
alias_method :<<, :write
5252

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

55-
# Retry reading
56-
def rescue_readable
57-
yield
58-
rescue IO::WaitReadable
59-
if IO.select([socket], nil, nil, read_timeout)
60-
retry
61-
else
58+
if RUBY_VERSION < "2.0.0"
59+
# Retry reading
60+
def rescue_readable
61+
yield
62+
rescue IO::WaitReadable
63+
retry if IO.select([socket], nil, nil, read_timeout)
64+
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
65+
end
66+
67+
# Retry writing
68+
def rescue_writable
69+
yield
70+
rescue IO::WaitWritable
71+
retry if IO.select(nil, [socket], nil, write_timeout)
72+
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
73+
end
74+
else
75+
require "io/wait"
76+
77+
# Retry reading
78+
def rescue_readable
79+
yield
80+
rescue IO::WaitReadable
81+
retry if socket.to_io.wait_readable(read_timeout)
6282
raise TimeoutError, "Read timed out after #{read_timeout} seconds"
6383
end
64-
end
6584

66-
# Retry writing
67-
def rescue_writable
68-
yield
69-
rescue IO::WaitWritable
70-
if IO.select(nil, [socket], nil, write_timeout)
71-
retry
72-
else
85+
# Retry writing
86+
def rescue_writable
87+
yield
88+
rescue IO::WaitWritable
89+
retry if socket.to_io.wait_writable(write_timeout)
7390
raise TimeoutError, "Write timed out after #{write_timeout} seconds"
7491
end
7592
end

lib/http/timeout/per_operation.rb

+10-4
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,17 @@ def write(data)
5959
# Read data from the socket
6060
def readpartial(size)
6161
loop do
62-
result = socket.read_nonblock(size, :exception => false)
62+
result = rescue_readable do
63+
socket.read_nonblock(size, :exception => false)
64+
end
65+
6366
if result.nil?
6467
return :eof
6568
elsif result != :wait_readable
6669
return result
6770
end
6871

69-
unless IO.select([socket], nil, nil, read_timeout)
72+
unless socket.to_io.wait_readable(read_timeout)
7073
fail TimeoutError, "Read timed out after #{read_timeout} seconds"
7174
end
7275
end
@@ -75,10 +78,13 @@ def readpartial(size)
7578
# Write data to the socket
7679
def write(data)
7780
loop do
78-
result = socket.write_nonblock(data, :exception => false)
81+
result = rescue_writable do
82+
socket.write_nonblock(data, :exception => false)
83+
end
84+
7985
return result unless result == :wait_writable
8086

81-
unless IO.select(nil, [socket], nil, write_timeout)
87+
unless socket.to_io.wait_writable(write_timeout)
8288
fail TimeoutError, "Read timed out after #{write_timeout} seconds"
8389
end
8490
end

0 commit comments

Comments
 (0)