THRIFT-3641 Ruby client should try to connect to every result of getaddrinfo
Client: Ruby
Patch: Nobuaki Sukegawa
This closes #872
diff --git a/lib/rb/lib/thrift/transport/socket.rb b/lib/rb/lib/thrift/transport/socket.rb
index 2b7ca09..517d112 100644
--- a/lib/rb/lib/thrift/transport/socket.rb
+++ b/lib/rb/lib/thrift/transport/socket.rb
@@ -33,26 +33,28 @@
attr_accessor :handle, :timeout
def open
- begin
- addrinfo = ::Socket::getaddrinfo(@host, @port, nil, ::Socket::SOCK_STREAM).first
- @handle = ::Socket.new(addrinfo[4], ::Socket::SOCK_STREAM, 0)
- @handle.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
- sockaddr = ::Socket.sockaddr_in(addrinfo[1], addrinfo[3])
+ for addrinfo in ::Socket::getaddrinfo(@host, @port, nil, ::Socket::SOCK_STREAM) do
begin
- @handle.connect_nonblock(sockaddr)
- rescue Errno::EINPROGRESS
- unless IO.select(nil, [ @handle ], nil, @timeout)
- raise TransportException.new(TransportException::NOT_OPEN, "Connection timeout to #{@desc}")
- end
+ socket = ::Socket.new(addrinfo[4], ::Socket::SOCK_STREAM, 0)
+ socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
+ sockaddr = ::Socket.sockaddr_in(addrinfo[1], addrinfo[3])
begin
- @handle.connect_nonblock(sockaddr)
- rescue Errno::EISCONN
+ socket.connect_nonblock(sockaddr)
+ rescue Errno::EINPROGRESS
+ unless IO.select(nil, [ socket ], nil, @timeout)
+ next
+ end
+ begin
+ socket.connect_nonblock(sockaddr)
+ rescue Errno::EISCONN
+ end
end
+ return @handle = socket
+ rescue StandardError => e
+ next
end
- @handle
- rescue StandardError => e
- raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}")
end
+ raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}")
end
def open?
diff --git a/lib/rb/spec/socket_spec.rb b/lib/rb/spec/socket_spec.rb
index e6b6732..8e1ef50 100644
--- a/lib/rb/spec/socket_spec.rb
+++ b/lib/rb/spec/socket_spec.rb
@@ -35,7 +35,7 @@
it_should_behave_like "a socket"
it "should raise a TransportException when it cannot open a socket" do
- ::Socket.should_receive(:new).and_raise(StandardError)
+ ::Socket.should_receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
lambda { @socket.open }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
end