From: Akira Tanaka Date: 2011-08-03T12:42:57+09:00 Subject: [ruby-core:38738] [Ruby 1.9 - Feature #5101] allow optional timeout for TCPSocket.new Issue #5101 has been updated by Akira Tanaka. File socket-tcp-connect-timeout.patch added I made a pactch for connect_timeout for Socket.tcp. with timeout: % time ./ruby -rsocket -e 'Socket.tcp("192.0.2.1", 80, :connect_timeout=>1)' /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:48:in `rescue in connect_internal': Connection timed out - user specified timeout (Errno::ETIMEDOUT) from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:44:in `connect_internal' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:108:in `connect' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:277:in `block in tcp' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:181:in `each' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:181:in `foreach' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:267:in `tcp' from -e:1:in `
' ./ruby -rsocket -e 'Socket.tcp("192.0.2.1", 80, :connect_timeout=>1)' 0.12s user 0.00s system 10% cpu 1.126 total without timeout: % time ./ruby -rsocket -e 'Socket.tcp("192.0.2.1", 80)' /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:56:in `connect': Connection timed out - connect(2) (Errno::ETIMEDOUT) from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:56:in `connect_internal' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:108:in `connect' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:277:in `block in tcp' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:181:in `each' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:181:in `foreach' from /home/akr/ruby/tst1/lib/ruby/1.9.1/socket.rb:267:in `tcp' from -e:1:in `
' ./ruby -rsocket -e 'Socket.tcp("192.0.2.1", 80)' 0.12s user 0.00s system 0% cpu 3:09.51 total ---------------------------------------- Feature #5101: allow optional timeout for TCPSocket.new http://redmine.ruby-lang.org/issues/5101 Author: Eric Wong Status: Assigned Priority: Low Assignee: Akira Tanaka Category: ext Target version: 1.9.x Proposed API would be: TCPSocket.new(remote_host, remote_port, connect_timeout: 0.5, local_host: nil, local_port: nil) Or: TCPSocket.new(remote_host, remote_port, connect_timeout: 0.5) For the common case. This would only timeout for establishing the TCP connection, not DNS resolution. DNS resolution can be covered by Feature #5100. The existing form for the (rarely-used) local_host/local_port args will still be supported for backwards compatibility: TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil) The current construct for doing a non-blocking connect with timeout is too verbose: addr = Socket.pack_sockaddr_in(9418, "127.0.0.1") s = Socket.new(:AF_INET, :SOCK_STREAM, 0) begin s.connect_nonblock(addr) rescue Errno::EINPROGRESS IO.select(nil, [s], nil, 0.5) or raise Timeout::Error end And could be replaced with: TCPSocket.new("127.0.0.1", 9418, connect_timeout: 0.5) I am not sure what exception TCPSocket.new should return. Timeout::Error seems like a reasonable choice... -- http://redmine.ruby-lang.org