diff --git a/lib/moped/connection/socket/connectable.rb b/lib/moped/connection/socket/connectable.rb index 3003a47..2d45d0a 100644 --- a/lib/moped/connection/socket/connectable.rb +++ b/lib/moped/connection/socket/connectable.rb @@ -4,6 +4,7 @@ module Socket module Connectable attr_reader :host, :port + attr_accessor :timeout # Is the socket connection alive? # @@ -44,7 +45,14 @@ def self.included(klass) # @since 1.2.0 def read(length) check_if_alive! - handle_socket_errors { super } + handle_socket_errors { + if Kernel.select([self], nil, [self], @timeout) + super + else + raise Errors::ConnectionFailure, + "timeout #{@timeout} exceeded on read from #{host}:#{port}" + end + } end # Write to the socket. @@ -145,9 +153,7 @@ def connect(host, port, timeout) sock = new(host, port) sock.set_encoding('binary') timeout_val = [ timeout, 0 ].pack("l_2") - sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) - sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVTIMEO, timeout_val) - sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDTIMEO, timeout_val) + sock.timeout = timeout sock end rescue Timeout::Error diff --git a/spec/moped/connection/socket/tcp_spec.rb b/spec/moped/connection/socket/tcp_spec.rb new file mode 100644 index 0000000..46649d3 --- /dev/null +++ b/spec/moped/connection/socket/tcp_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' +require 'moped/connection/socket/tcp' + +describe Moped::Connection::Socket::TCP do + it "raises Moped::Errors::ConnectionFailure if no response within timeout" do + Timeout::timeout(10) do + expect { + # this test relies on the mongo protocol expecting the client + # to speak first + socket = described_class.connect('127.0.0.1', 27017, 2) + socket.read(100) + }.to raise_exception Moped::Errors::ConnectionFailure + end + end +end