From 847625359de606494aec3cabc6cb3f98cb517a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Oct 2026 02:24:05 +0200 Subject: [PATCH] HTTP connect: re-arm the select() set on each wait, and skip failed sockets select() clears the sockets that aren't ready, so after one 0.5 s slice with no connection the loop waited on an empty set and every connect slower than that ran out the whole timeout. A socket that turns writable because its connect failed was also taken as connected. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/Net/HTTPClient.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp index 46d4454e15..97d73d2369 100644 --- a/Common/Net/HTTPClient.cpp +++ b/Common/Net/HTTPClient.cpp @@ -172,6 +172,7 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { continue; } // There is at least 1 socket candidate. + const fd_set allFds = fds; int selectResult = 0; long timeoutHalfSeconds = floor(2 * timeout); @@ -187,6 +188,8 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { } --timeoutHalfSeconds; + // select() clears the sockets that aren't ready, so each wait needs a fresh copy. + fds = allFds; selectResult = select(maxfd, nullptr, &fds, nullptr, &tv); if (cancelConnect && *cancelConnect) { WARN_LOG(Log::HTTP, "connect: cancelled (1): %s:%d", host_.c_str(), port_); @@ -196,15 +199,21 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { if (selectResult > 0) { // Something connected. Pick the first one that did (if multiple.) for (int sock : sockets) { - if ((intptr_t)sock_ == -1 && FD_ISSET(sock, &fds)) { + // Writable can also mean the attempt failed (refused, say). + int soError = 0; + socklen_t soErrorLen = sizeof(soError); + bool connected = FD_ISSET(sock, &fds) && getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&soError, &soErrorLen) == 0 && soError == 0; + if ((intptr_t)sock_ == -1 && connected) { sock_ = sock; } else { closesocket(sock); } } - // Great, now we're good to go. - return true; + if ((intptr_t)sock_ != -1) { + // Great, now we're good to go. + return true; + } } else { // Fail. Close all the sockets. for (int sock : sockets) {