mirror of
https://github.com/ruby/ruby.git
synced 2025-09-15 16:44:01 +02:00
merge revision(s) 1683dadb19
: [Backport #21088]
Do not save ResolutionError if resolution succeeds for any address family (#12678) * Do not save ResolutionError if resolution succeeds for any address family Socket with Happy Eyeballs Version 2 performs connection attempts and name resolution in parallel. In the existing implementation, if a connection attempt failed for one address family while name resolution was still in progress for the other, and that name resolution later failed, the method would terminate with a name resolution error. This behavior was intended to ensure that the final error reflected the most recent failure, potentially overriding an earlier error. However, [Bug #21088](https://bugs.ruby-lang.org/issues/21088) made me realize that terminating with a name resolution error is unnatural when name resolution succeeded for at least one address family. This PR modifies the behavior so that if name resolution succeeds for one address family, any name resolution error from the other is not saved. This PR includes the following changes: * Do not display select(2) as the system call that caused the raised error, as it is for internal processing * Fix bug: Get errno with Socket::SO_ERROR in Windows environment with a workaround for tests not passing
This commit is contained in:
parent
e5403bd137
commit
319c3c7038
5 changed files with 50 additions and 18 deletions
|
@ -892,7 +892,6 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
|||
}
|
||||
|
||||
status = rb_thread_fd_select(nfds, &arg->readfds, &arg->writefds, NULL, delay_p);
|
||||
syscall = "select(2)";
|
||||
|
||||
now = current_clocktime_ts();
|
||||
if (is_timeout_tv(resolution_delay_expires_at, now)) {
|
||||
|
@ -998,9 +997,11 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
|||
|
||||
if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err &&
|
||||
arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
if (!resolution_store.v4.finished || resolution_store.v4.has_error) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
}
|
||||
resolution_store.v6.has_error = true;
|
||||
} else {
|
||||
resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai;
|
||||
|
@ -1015,9 +1016,11 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
|||
resolution_store.v4.finished = true;
|
||||
|
||||
if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
if (!resolution_store.v6.finished || resolution_store.v6.has_error) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
}
|
||||
resolution_store.v4.has_error = true;
|
||||
} else {
|
||||
resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai;
|
||||
|
@ -1057,9 +1060,11 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
|||
resolution_store.v6.finished = true;
|
||||
|
||||
if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
if (!resolution_store.v4.finished || resolution_store.v4.has_error) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
}
|
||||
resolution_store.v6.has_error = true;
|
||||
} else {
|
||||
resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai;
|
||||
|
@ -1075,9 +1080,11 @@ init_fast_fallback_inetsock_internal(VALUE v)
|
|||
resolution_store.v4.finished = true;
|
||||
|
||||
if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
if (!resolution_store.v6.finished || resolution_store.v6.has_error) {
|
||||
last_error.type = RESOLUTION_ERROR;
|
||||
last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
|
||||
syscall = "getaddrinfo(3)";
|
||||
}
|
||||
resolution_store.v4.has_error = true;
|
||||
} else {
|
||||
resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai;
|
||||
|
|
|
@ -833,7 +833,7 @@ class Socket < BasicSocket
|
|||
if except_sockets&.any?
|
||||
except_sockets.each do |except_socket|
|
||||
failed_ai = connecting_sockets.delete except_socket
|
||||
sockopt = except_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME)
|
||||
sockopt = except_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
|
||||
except_socket.close
|
||||
ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
|
||||
last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int)
|
||||
|
@ -862,7 +862,10 @@ class Socket < BasicSocket
|
|||
unless (Socket.const_defined?(:EAI_ADDRFAMILY)) &&
|
||||
(result.is_a?(Socket::ResolutionError)) &&
|
||||
(result.error_code == Socket::EAI_ADDRFAMILY)
|
||||
last_error = result
|
||||
other = family_name == :ipv6 ? :ipv4 : :ipv6
|
||||
if !resolution_store.resolved?(other) || !resolution_store.resolved_successfully?(other)
|
||||
last_error = result
|
||||
end
|
||||
end
|
||||
else
|
||||
resolution_store.add_resolved(family_name, result)
|
||||
|
@ -1068,7 +1071,7 @@ class Socket < BasicSocket
|
|||
end
|
||||
|
||||
def resolved_successfully?(family)
|
||||
resolved?(family) && !!@error_dict[family]
|
||||
resolved?(family) && !@error_dict[family]
|
||||
end
|
||||
|
||||
def resolved_all_families?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue