git: d53af4112273 - main - libfetch: Apply timeout to connection attempts
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 29 Jun 2026 15:52:15 UTC
The branch main has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=d53af4112273f7b234a1cdd6694b3a7ca0aae0eb
commit d53af4112273f7b234a1cdd6694b3a7ca0aae0eb
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-06-27 15:34:53 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-06-29 13:49:19 +0000
libfetch: Apply timeout to connection attempts
Mark the socket non-blocking before connecting and poll for completion,
applying fetchTimeout if set.
MFC after: 1 week
---
lib/libfetch/common.c | 47 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 6 deletions(-)
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index c1888a1518a0..d1a897b98827 100644
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -593,10 +593,13 @@ fetch_socks5_getenv(char **host, int *port)
conn_t *
fetch_connect(const char *host, int port, int af, int verbose)
{
+ struct timeval now, timeout, delta;
+ struct pollfd pfd;
struct addrinfo *cais = NULL, *sais = NULL, *cai, *sai;
const char *bindaddr;
conn_t *conn = NULL;
int err = 0, sd = -1;
+ int deltams;
char *sockshost;
int socksport;
@@ -654,15 +657,47 @@ fetch_connect(const char *host, int port, int af, int verbose)
fetch_verbose("failed to bind to %s", bindaddr);
goto syserr;
}
+ /* make the socket non-blocking */
+ (void)fcntl(sd, F_SETFL, O_NONBLOCK);
+ /* start the clock */
+ if (fetchTimeout > 0) {
+ gettimeofday(&timeout, NULL);
+ timeout.tv_sec += fetchTimeout;
+ deltams = fetchTimeout * 1000;
+ }
/* attempt to connect to server address */
- while ((err = connect(sd, sai->ai_addr, sai->ai_addrlen)) < 0) {
- if (errno == EINTR && fetchRestartCalls)
- continue;
+ if ((err = connect(sd, sai->ai_addr, sai->ai_addrlen)) == 0)
break;
+ /* wait for connection */
+ if (errno == EINPROGRESS) {
+ deltams = INFTIM;
+ pfd.fd = sd;
+ pfd.events = POLLOUT;
+ for (;;) {
+ /* wait for something to happen */
+ if (poll(&pfd, 1, deltams) >= 0)
+ break;
+ if (errno == EINTR && !fetchRestartCalls)
+ break;
+ /* check the clock */
+ if (fetchTimeout > 0) {
+ gettimeofday(&now, NULL);
+ if (!timercmp(&timeout, &now, >)) {
+ errno = ETIMEDOUT;
+ pfd.revents = POLLERR;
+ break;
+ }
+ timersub(&timeout, &now, &delta);
+ deltams = delta.tv_sec * 1000 +
+ delta.tv_usec / 1000;
+ }
+ }
+ if (pfd.revents == POLLOUT) {
+ /* connection established */
+ err = 0;
+ break;
+ }
}
- /* success? */
- if (err == 0)
- break;
/* clean up before next attempt */
close(sd);
sd = -1;