From ffd032a60bfc25d34efe05d6340767a8ea00a3b4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 14 Sep 2026 11:20:25 +0900 Subject: [PATCH] Report the IPv4 resolution error after EAI_ADDRFAMILY for IPv6 EAI_ADDRFAMILY left the IPv6 result looking successful, so a later IPv4 resolution error was not recorded and TCPSocket.new raised Socket::ResolutionError with error_code 0. When the IPv6 notification failed, EAI_ADDRFAMILY was recorded instead and hid the IPv4 error. Co-Authored-By: Claude Opus 5 --- ext/socket/ipsocket.c | 9 +++++---- test/socket/test_tcp.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index f36d6a29a97..426c423f52d 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -1102,9 +1102,9 @@ init_fast_fallback_inetsock_internal(VALUE v) if (resolved_type[0] == IPV6_HOSTNAME_RESOLVED) { resolution_store.v6.finished = true; - if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err && - arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY) { - if (!resolution_store.v4.finished || resolution_store.v4.has_error) { + if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err) { + if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY && + (!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)"; @@ -1176,7 +1176,8 @@ init_fast_fallback_inetsock_internal(VALUE v) resolution_store.v6.finished = true; if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err) { - if (!resolution_store.v4.finished || resolution_store.v4.has_error) { + if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY && + (!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)"; diff --git a/test/socket/test_tcp.rb b/test/socket/test_tcp.rb index 0c1e3cc4e39..e17f1d06dd2 100644 --- a/test/socket/test_tcp.rb +++ b/test/socket/test_tcp.rb @@ -415,6 +415,21 @@ class TestSocket_TCPSocket < Test::Unit::TestCase end end + def test_initialize_v4_hostname_resolution_failure_after_v6_address_family_error + return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/ + omit "EAI_ADDRFAMILY is not defined" unless defined?(Socket::EAI_ADDRFAMILY) + + e = assert_raise(Socket::ResolutionError) do + TCPSocket.new( + "localhost", + 12345, + fast_fallback: true, + test_mode_settings: { delay: { ipv4: 100 }, error: { ipv6: Socket::EAI_ADDRFAMILY, ipv4: Socket::EAI_FAIL } } + ) + end + assert_equal(Socket::EAI_FAIL, e.error_code) + end + def test_initialize_v6_connected_socket_with_v6_address return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/