Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fd4b274

Browse files
authored
Do not wait connection attempt delay without in progress fds (#12087)
Do not wait Connection Attempt Delay without in progress fds Reset Connection Attempt Delay when connection fails and there is no other socket connection in progress. This is intended to resolve an issue that was temporarily worked around in Pull Request #12062. `TCPServer::new` (used in tests such as `TestNetHTTP_v1_2_chunked#test_timeout_during_non_chunked_streamed_HTTP_session_write`) can only connect over either IPv6 or IPv4, depending on the environment. Since HEv2 attempts to connect over IPv6 first, environments where IPv6 connections are unavailable return ECONNREFUSED immediately. In such cases, the client should immediately retry the connection over IPv4. However, HEv2 includes a specification for a "Connection Attempt Delay," where it waits 250ms after the previous connection attempt before starting the next one. This delay causes Net::OpenTimeout (100ms) to be exceeded while waiting for the next connection attempt to start. With this change, when a connection attempt fails, if there are sockets still attempting to connect and there are addresses yet to be tried, the Connection Attempt Delay will be resetted, allowing the next connection attempt to start immediately. --- Additionally, the following minor fixes have been made: - The `nfds` value used for select(2) is now reset with each wait.
1 parent 54ff9d3 commit fd4b274

File tree

2 files changed

+21
-22
lines changed

2 files changed

+21
-22
lines changed

ext/socket/ipsocket.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,6 @@ init_fast_fallback_inetsock_internal(VALUE v)
572572
struct wait_fast_fallback_arg wait_arg;
573573
struct timeval *ends_at = NULL;
574574
struct timeval delay = (struct timeval){ -1, -1 };
575-
wait_arg.nfds = 0;
576575
wait_arg.writefds = NULL;
577576
wait_arg.status = 0;
578577

@@ -916,6 +915,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
916915
wait_arg.delay = NULL;
917916
}
918917

918+
wait_arg.nfds = 0;
919919
if (arg->connection_attempt_fds_size) {
920920
FD_ZERO(wait_arg.writefds);
921921
int n = 0;
@@ -995,25 +995,24 @@ init_fast_fallback_inetsock_internal(VALUE v)
995995
last_error.type = SYSCALL_ERROR;
996996
last_error.ecode = errno;
997997

998-
if (any_addrinfos(&resolution_store) ||
999-
in_progress_fds(arg->connection_attempt_fds_size) ||
1000-
!resolution_store.is_all_finised) {
1001-
if (!in_progress_fds(arg->connection_attempt_fds_size)) {
1002-
user_specified_connect_timeout_at = NULL;
1003-
}
1004-
} else {
1005-
if (local_status < 0) {
1006-
host = arg->local.host;
1007-
serv = arg->local.serv;
1008-
} else {
1009-
host = arg->remote.host;
1010-
serv = arg->remote.serv;
1011-
}
1012-
if (last_error.type == RESOLUTION_ERROR) {
1013-
rsock_raise_resolution_error(syscall, last_error.ecode);
1014-
} else {
1015-
rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
998+
if (!in_progress_fds(arg->connection_attempt_fds_size)) {
999+
if (any_addrinfos(&resolution_store)) {
1000+
connection_attempt_delay_expires_at = NULL;
1001+
} else if (resolution_store.is_all_finised) {
1002+
if (local_status < 0) {
1003+
host = arg->local.host;
1004+
serv = arg->local.serv;
1005+
} else {
1006+
host = arg->remote.host;
1007+
serv = arg->remote.serv;
1008+
}
1009+
if (last_error.type == RESOLUTION_ERROR) {
1010+
rsock_raise_resolution_error(syscall, last_error.ecode);
1011+
} else {
1012+
rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
1013+
}
10161014
}
1015+
user_specified_connect_timeout_at = NULL;
10171016
}
10181017

10191018
/* check for hostname resolution */

test/net/http/test_http.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,8 +568,8 @@ def test_timeout_during_HTTP_session_write
568568
conn.open_timeout = EnvUtil.apply_timeout_scale(0.1)
569569

570570
th = Thread.new do
571-
err = !windows? ? [Net::WriteTimeout, Net::OpenTimeout] : Net::ReadTimeout
572-
assert_raise(*err) do
571+
err = !windows? ? Net::WriteTimeout : Net::ReadTimeout
572+
assert_raise(err) do
573573
assert_warning(/Content-Type did not set/) do
574574
conn.post('/', "a"*50_000_000)
575575
end
@@ -600,7 +600,7 @@ def test_timeout_during_non_chunked_streamed_HTTP_session_write
600600
req.body_stream = StringIO.new(data)
601601

602602
th = Thread.new do
603-
assert_raise(Net::WriteTimeout, Net::OpenTimeout) { conn.request(req) }
603+
assert_raise(Net::WriteTimeout) { conn.request(req) }
604604
end
605605
assert th.join(10)
606606
}

0 commit comments

Comments
 (0)