summaryrefslogtreecommitdiff
path: root/ext/socket/lib/socket.rb
diff options
context:
space:
mode:
authorMisaki Shioi <31817032+shioimm@users.noreply.github.com>2025-12-27 18:26:56 +0900
committerGitHub <noreply@github.com>2025-12-27 18:26:56 +0900
commita8c3d5e127776d74eb068c95610277feb99adcf0 (patch)
tree4f34296daf86c8531a4e9ec12bec696bae6e7d34 /ext/socket/lib/socket.rb
parent3c9e61f5ef8190e082b36e056f59be49692ae8aa (diff)
Fix: Do not fast_fallback if local_port is explicitly specified (#15732)
`fast fallback` cannot be used with explicitly specified local port, because concurrent binds to the same `local_host:local_port` can raise `Errno::EADDRINUSE`. This issue is more likely to occur on hosts with `IPV6_V6ONLY` disabled, because IPv6 binds can also occupy IPv4-mapped IPv6 address space.
Diffstat (limited to 'ext/socket/lib/socket.rb')
-rw-r--r--ext/socket/lib/socket.rb5
1 files changed, 2 insertions, 3 deletions
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index e74eaec43a..36fcceaee9 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -660,12 +660,11 @@ class Socket < BasicSocket
# puts sock.read
# }
def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil, fast_fallback: tcp_fast_fallback, &) # :yield: socket
-
if open_timeout && (connect_timeout || resolv_timeout)
raise ArgumentError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout"
end
- sock = if fast_fallback && !(host && ip_address?(host))
+ sock = if fast_fallback && !(host && ip_address?(host)) && !(local_port && local_port.to_i != 0)
tcp_with_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
else
tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
@@ -736,7 +735,7 @@ class Socket < BasicSocket
if local_addrinfos.any?
local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily }
- if local_addrinfo.nil? # Connecting addrinfoと同じアドレスファミリのLocal addrinfoがない
+ if local_addrinfo.nil?
if resolution_store.any_addrinfos?
# Try other Addrinfo in next "while"
next