mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-08-10 00:01:27 -04:00
fixing selector timeout errors closing all connections and ignoring
resolvers All kinds of errors happening during the select loop, will be handled as abrupt select loop errors, and terminate all connections; this also includes timmeout errors. This is not ideal, for some reasons: connection timeout errors happening on the loop close all connections, although it may be only triggered for one (or a subset of) connection for which the timeout should trigger; second, errors on the DS channel propagate errors to connections indirectly (the emission mentioned above), wrongly (connections for different hostnames not yet queried, will also fail with timeout), and won't clean the resolver state (so subsequent queries will be done for the same hostname which failed in the first place). This fix is a first step to solving this problem. It does not totally address the first, but i'll fix dealing with errors from the second use-case.
This commit is contained in:
parent
d8e5894979
commit
6c911768fe
@ -276,6 +276,12 @@ module HTTPX
|
||||
@state == :open || @state == :inactive
|
||||
end
|
||||
|
||||
def raise_timeout_error(interval)
|
||||
error = HTTPX::TimeoutError.new(interval, "timed out while waiting on select")
|
||||
error.set_backtrace(caller)
|
||||
on_error(error)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def connect
|
||||
|
@ -118,6 +118,10 @@ module HTTPX
|
||||
@timeouts.values_at(*hosts).reject(&:empty?).map(&:first).min
|
||||
end
|
||||
|
||||
def raise_timeout_error(interval)
|
||||
do_retry(interval)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def calculate_interests
|
||||
@ -134,10 +138,10 @@ module HTTPX
|
||||
dwrite if calculate_interests == :w
|
||||
end
|
||||
|
||||
def do_retry
|
||||
def do_retry(loop_time = nil)
|
||||
return if @queries.empty? || !@start_timeout
|
||||
|
||||
loop_time = Utils.elapsed_time(@start_timeout)
|
||||
loop_time ||= Utils.elapsed_time(@start_timeout)
|
||||
|
||||
query = @queries.first
|
||||
|
||||
|
@ -74,7 +74,10 @@ class HTTPX::Selector
|
||||
|
||||
readers, writers = IO.select(r, w, nil, interval)
|
||||
|
||||
raise HTTPX::TimeoutError.new(interval, "timed out while waiting on select") if readers.nil? && writers.nil? && interval
|
||||
if readers.nil? && writers.nil? && interval
|
||||
[*r, *w].each { |io| io.raise_timeout_error(interval) }
|
||||
return
|
||||
end
|
||||
rescue IOError, SystemCallError
|
||||
@selectables.reject!(&:closed?)
|
||||
retry
|
||||
@ -108,7 +111,11 @@ class HTTPX::Selector
|
||||
when nil then return
|
||||
end
|
||||
|
||||
raise HTTPX::TimeoutError.new(interval, "timed out while waiting on select") unless result || interval.nil?
|
||||
unless result || interval.nil?
|
||||
io.raise_timeout_error(interval)
|
||||
return
|
||||
end
|
||||
# raise HTTPX::TimeoutError.new(interval, "timed out while waiting on select")
|
||||
|
||||
yield io
|
||||
rescue IOError, SystemCallError
|
||||
|
@ -72,6 +72,9 @@ module HTTPX
|
||||
def timeout: () -> Numeric?
|
||||
|
||||
def deactivate: () -> void
|
||||
|
||||
def raise_timeout_error: (Numeric interval) -> void
|
||||
|
||||
private
|
||||
|
||||
def initialize: (String, URI::Generic, options) -> untyped
|
||||
|
@ -27,6 +27,8 @@ module HTTPX
|
||||
|
||||
def timeout: () -> Numeric?
|
||||
|
||||
def raise_timeout_error: (Numeric interval) -> void
|
||||
|
||||
private
|
||||
|
||||
def initialize: (ip_family family, options options) -> void
|
||||
@ -35,7 +37,7 @@ module HTTPX
|
||||
|
||||
def consume: () -> void
|
||||
|
||||
def do_retry: () -> void
|
||||
def do_retry: (?Numeric loop_time) -> void
|
||||
|
||||
def dread: (Integer) -> void
|
||||
| () -> void
|
||||
|
Loading…
x
Reference in New Issue
Block a user