The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=848f360c8f9ae8d1d97c61f5d63fc624926d5dcd

commit 848f360c8f9ae8d1d97c61f5d63fc624926d5dcd
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2026-07-13 06:43:37 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
CommitDate: 2026-07-13 06:43:37 +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
    Reviewed by:    op
    Differential Revision:  https://reviews.freebsd.org/D57909
---
 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;

Reply via email to