Skip to content

Commit 90ab29b

Browse files
committed
Use all results returned by getaddrinfo(3), if necessary
I have seen getaddrinfo(3) return IPv6 addresses before IPv4 addresses when a hostname resolves to both. It is still more common for Redis to listen only on a v4 address than a v6 address or both a v4 and a v6 address. When getaddrinfo(3) would returns a v6 address that Redis is not listening on, the user would see ECONNREFUSED or similar without this patch. This is clearly undesirable behavior. Additionally, per the getaddrinfo(3) man page, we should try to use the addresses it returns in the order they are returned.
1 parent b146d74 commit 90ab29b

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

lib/redis/connection/ruby.rb

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,9 @@ class TCPSocket < ::Socket
114114

115115
include SocketMixin
116116

117-
def self.connect(host, port, timeout)
118-
addr = ::Socket.getaddrinfo(host, nil, Socket::AF_UNSPEC)
119-
sock = new(::Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
120-
sockaddr = ::Socket.pack_sockaddr_in(port, addr[0][3])
117+
def self.connect_addrinfo(ai, port, timeout)
118+
sock = new(::Socket.const_get(ai[0]), Socket::SOCK_STREAM, 0)
119+
sockaddr = ::Socket.pack_sockaddr_in(port, ai[3])
121120

122121
begin
123122
sock.connect_nonblock(sockaddr)
@@ -134,6 +133,25 @@ def self.connect(host, port, timeout)
134133

135134
sock
136135
end
136+
137+
def self.connect(host, port, timeout)
138+
addrinfo = ::Socket.getaddrinfo(host, nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM)
139+
140+
# From the man page for getaddrinfo(3):
141+
#
142+
# Normally, the application should try using the addresses in the
143+
# order in which they are returned. The sorting function used
144+
# within getaddrinfo() is defined in RFC 3484 [...].
145+
#
146+
addrinfo.each_with_index do |ai, i|
147+
begin
148+
return connect_addrinfo(ai, port, timeout)
149+
rescue SystemCallError
150+
# Raise if this was our last attempt.
151+
raise if addrinfo.length == i+1
152+
end
153+
end
154+
end
137155
end
138156

139157
class UNIXSocket < ::Socket

0 commit comments

Comments
 (0)