@@ -165,29 +165,66 @@ def address_resolve(hostname)
165165 ::Resolv . getaddresses ( hostname )
166166 end
167167
168+
169+ if IO . method_defined? ( :timeout )
170+ private def get_timeout ( io )
171+ io . timeout
172+ end
173+ else
174+ private def get_timeout ( io )
175+ nil
176+ end
177+ end
178+
168179 # @asynchronous May be non-blocking..
169180 def io_wait ( io , events , timeout = nil )
170181 fiber = Fiber . current
171182
172183 if timeout
184+ # If an explicit timeout is specified, we expect that the user will handle it themselves:
173185 timer = @timers . after ( timeout ) do
174186 fiber . transfer
175187 end
188+ elsif timeout = get_timeout ( io )
189+ # Otherwise, if we default to the io's timeout, we raise an exception:
190+ timer = @timers . after ( timeout ) do
191+ fiber . raise ( ::IO ::TimeoutError , "Timeout while waiting for IO to become ready!" )
192+ end
176193 end
177194
178195 return @selector . io_wait ( fiber , io , events )
179196 ensure
180197 timer &.cancel
181198 end
182-
199+
183200 if ::IO ::Event ::Support . buffer?
184201 def io_read ( io , buffer , length , offset = 0 )
185- @selector . io_read ( Fiber . current , io , buffer , length , offset )
202+ fiber = Fiber . current
203+
204+ if timeout = get_timeout ( io )
205+ timer = @timers . after ( timeout ) do
206+ fiber . raise ( ::IO ::TimeoutError , "execution expired" )
207+ end
208+ end
209+
210+ @selector . io_read ( fiber , io , buffer , length , offset )
211+ ensure
212+ timer &.cancel
186213 end
187214
188215 if RUBY_ENGINE != "ruby" || RUBY_VERSION >= "3.3.0"
189216 def io_write ( io , buffer , length , offset = 0 )
190- @selector . io_write ( Fiber . current , io , buffer , length , offset )
217+ fiber = Fiber . current
218+
219+ if timeout = get_timeout ( io )
220+ timer = @timers . after ( timeout ) do
221+ fiber . raise ( ::IO ::TimeoutError , "execution expired" )
222+ end
223+ end
224+
225+ @selector . io_write ( fiber , io , buffer , length , offset )
226+ ensure
227+ timer &.cancel
191228 end
192229 end
193230 end
0 commit comments