From 377becc14c97daa536147eac6cec2b901b9ebe08 Mon Sep 17 00:00:00 2001 From: link2xt Date: Fri, 24 Jul 2026 16:44:50 +0000 Subject: [PATCH] fix: don't break out of run_connection_attempts with `futures` left to try If we ran out of running connection attempts, but there are still futures not added to the connection attempt set, we should not break out with the list of errors yet, but move another future into the attempt set even if the delay has not expired yet. Otherwise it is possible to resolve the hostname into two IPs, try one that fails immediately, then break out of the loop without trying the second one and only report the error for the first one. It is still not nice that we may start another connection attempt right before the next delay expires, so we may start two connections attempts almost simultaneously, but it is not critical. --- src/net.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/net.rs b/src/net.rs index 01cf1c03c6..df7c8d6ae9 100644 --- a/src/net.rs +++ b/src/net.rs @@ -184,10 +184,6 @@ where let mut all_errors = Vec::new(); let res = loop { - if let Some(fut) = futures.next() { - connection_attempt_set.spawn(fut); - } - tokio::select! { biased; @@ -209,14 +205,18 @@ where } } None => { - // Out of connection attempts. - // - // Break out of the loop and return error. - break if all_errors.is_empty() { - Err(format_err!("No connection attempts were made")) + if let Some(fut) = futures.next() { + connection_attempt_set.spawn(fut); } else { - Err(format_err!("All connection attempts failed: {}", all_errors.into_iter().map(|err| format!("{err:#}")).collect::>().join("; "))) - }; + // Out of connection attempts. + // + // Break out of the loop and return error. + break if all_errors.is_empty() { + Err(format_err!("No connection attempts were made")) + } else { + Err(format_err!("All connection attempts failed: {}", all_errors.into_iter().map(|err| format!("{err:#}")).collect::>().join("; "))) + }; + } } } },