Skip to content

Commit 1903ced

Browse files
authored
Merge pull request #224 from osyoyu/tcpsocket-open-timeout
Replace Timeout.timeout with TCPSocket.open(open_timeout:) when available
2 parents 58685b7 + 06d982f commit 1903ced

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

lib/net/http.rb

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,7 @@ def initialize(address, port = nil) # :nodoc:
11791179
@debug_output = options[:debug_output]
11801180
@response_body_encoding = options[:response_body_encoding]
11811181
@ignore_eof = options[:ignore_eof]
1182+
@tcpsocket_supports_open_timeout = nil
11821183

11831184
@proxy_from_env = false
11841185
@proxy_uri = nil
@@ -1672,14 +1673,36 @@ def connect
16721673
end
16731674

16741675
debug "opening connection to #{conn_addr}:#{conn_port}..."
1675-
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1676-
begin
1677-
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1678-
rescue => e
1679-
raise e, "Failed to open TCP connection to " +
1680-
"#{conn_addr}:#{conn_port} (#{e.message})"
1681-
end
1682-
}
1676+
begin
1677+
s =
1678+
case @tcpsocket_supports_open_timeout
1679+
when nil, true
1680+
begin
1681+
# Use built-in timeout in TCPSocket.open if available
1682+
sock = TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout)
1683+
@tcpsocket_supports_open_timeout = true
1684+
sock
1685+
rescue ArgumentError => e
1686+
raise if !(e.message.include?('unknown keyword: :open_timeout') || e.message.include?('wrong number of arguments (given 5, expected 2..4)'))
1687+
@tcpsocket_supports_open_timeout = false
1688+
1689+
# Fallback to Timeout.timeout if TCPSocket.open does not support open_timeout
1690+
Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1691+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1692+
}
1693+
end
1694+
when false
1695+
# The current Ruby is known to not support TCPSocket(open_timeout:).
1696+
# Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue.
1697+
Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1698+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1699+
}
1700+
end
1701+
rescue => e
1702+
e = Net::OpenTimeout.new(e) if e.is_a?(Errno::ETIMEDOUT) # for compatibility with previous versions
1703+
raise e, "Failed to open TCP connection to " +
1704+
"#{conn_addr}:#{conn_port} (#{e.message})"
1705+
end
16831706
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
16841707
debug "opened"
16851708
if use_ssl?

0 commit comments

Comments
 (0)