Skip to content

Commit 8c76f92

Browse files
committed
Check whether TCPSocket#initialize supports open_timeout once and without exceptions
* See discussion in #224 * This check is known to work on at least CRuby, TruffleRuby and JRuby. * Exceptions show up with `ruby -d`/`$DEBUG == true` and would show for every Net::HTTP instance.
1 parent 0f6986d commit 8c76f92

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

lib/net/http.rb

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,26 +1772,24 @@ def connect
17721772
end
17731773
private :connect
17741774

1775+
tcp_socket_parameters = TCPSocket.instance_method(:initialize).parameters
1776+
TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT = if tcp_socket_parameters != [[:rest]]
1777+
tcp_socket_parameters.include?([:key, :open_timeout])
1778+
else
1779+
# Use Socket.tcp to find out since there is no parameters information for TCPSocket#initialize
1780+
# See discussion in https://github.com/ruby/net-http/pull/224
1781+
Socket.method(:tcp).parameters.include?([:key, :open_timeout])
1782+
end
1783+
private_constant :TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
1784+
17751785
def timeouted_connect(conn_addr, conn_port)
1776-
if @tcpsocket_supports_open_timeout == nil || @tcpsocket_supports_open_timeout == true
1777-
# Try to use built-in open_timeout in TCPSocket.open if:
1778-
# - The current Ruby runtime is known to support it, or
1779-
# - It is unknown whether the current Ruby runtime supports it (so we'll try).
1780-
begin
1781-
sock = TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout)
1782-
@tcpsocket_supports_open_timeout = true
1783-
return sock
1784-
rescue ArgumentError => e
1785-
raise if !(e.message.include?('unknown keyword: :open_timeout') || e.message.include?('wrong number of arguments (given 5, expected 2..4)'))
1786-
@tcpsocket_supports_open_timeout = false
1787-
end
1786+
if TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
1787+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout)
1788+
else
1789+
Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1790+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1791+
}
17881792
end
1789-
1790-
# This Ruby runtime is known not to support `TCPSocket(open_timeout:)`.
1791-
# Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue.
1792-
Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1793-
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1794-
}
17951793
end
17961794
private :timeouted_connect
17971795

0 commit comments

Comments
 (0)