From b953dbd3c8178ed460e4356ecd07f6a7494b4d39 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 18 Jun 2026 13:34:54 +0900 Subject: [PATCH] Probe socket errors via SO_ERROR in TCPSocketProbe Calling connect_nonblock a second time to confirm a non-blocking connect is not portable. On BSD-based systems such as macOS the second connect returns EISCONN even after the asynchronous connect failed with ECONNREFUSED, so a down mirror was reported as reachable. Check the pending socket error with getsockopt(SO_ERROR) once IO.select reports the socket writable instead. Co-Authored-By: Claude Opus 4.8 --- bundler/lib/bundler/mirror.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bundler/lib/bundler/mirror.rb b/bundler/lib/bundler/mirror.rb index 494a6d6aef18..234c6bd37dcf 100644 --- a/bundler/lib/bundler/mirror.rb +++ b/bundler/lib/bundler/mirror.rb @@ -160,18 +160,18 @@ def replies?(mirror) def wait_for_writtable_socket(socket, address, timeout) if IO.select(nil, [socket], nil, timeout) - probe_writtable_socket(socket, address) + probe_writtable_socket(socket) else # TCP Handshake timed out, or there is something dropping packets false end end - def probe_writtable_socket(socket, address) - socket.connect_nonblock(address) - rescue Errno::EISCONN - true - rescue StandardError # Connection failed - false + def probe_writtable_socket(socket) + # Check the pending error on the socket rather than calling + # +connect_nonblock+ a second time. On BSD-based systems such as macOS a + # second connect returns +EISCONN+ even when the asynchronous connect + # failed, which would make a down mirror look reachable. + socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR).int == 0 end end end