]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
conncache: connection alive checks intervals
authorStefan Eissing <stefan@eissing.org>
Thu, 25 Jun 2026 11:25:35 +0000 (13:25 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 26 Jun 2026 11:52:26 +0000 (13:52 +0200)
Do not check if a particular connection is alive or not more than once
every second. We did this on every connection reuse which is overkill
when sending many requests to the same host.

Closes #22169

lib/conncache.c
lib/url.c
lib/url.h
lib/urldata.h

index 5ba236862200a5ed920c9d32728875c349428805..6fc29be4b4e207551a8f84acd196b07637f77dd2 100644 (file)
@@ -687,6 +687,7 @@ void Curl_conn_terminate(struct Curl_easy *data,
 struct cpool_reaper_ctx {
   size_t checked;
   size_t reaped;
+  struct curltime now;
 };
 
 static int cpool_reap_dead_cb(struct Curl_easy *data,
@@ -697,7 +698,7 @@ static int cpool_reap_dead_cb(struct Curl_easy *data,
 
   if(!terminate) {
     reaper->checked++;
-    terminate = Curl_conn_seems_dead(conn, data);
+    terminate = Curl_conn_seems_dead(conn, data, &reaper->now);
   }
   if(terminate) {
     /* stop the iteration here, pass back the connection that was pruned */
@@ -718,17 +719,19 @@ static int cpool_reap_dead_cb(struct Curl_easy *data,
 void Curl_cpool_prune_dead(struct Curl_easy *data)
 {
   struct cpool *cpool = cpool_get_instance(data);
-  struct cpool_reaper_ctx reaper;
   timediff_t elapsed;
 
   if(!cpool)
     return;
 
-  memset(&reaper, 0, sizeof(reaper));
   CPOOL_LOCK(cpool, data);
   elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &cpool->last_cleanup);
 
   if(elapsed >= 1000L) {
+    struct cpool_reaper_ctx reaper;
+
+    memset(&reaper, 0, sizeof(reaper));
+    reaper.now = *Curl_pgrs_now(data);
     while(cpool_foreach(data, cpool, &reaper, cpool_reap_dead_cb))
       ;
     cpool->last_cleanup = *Curl_pgrs_now(data);
index d0e0286d2fff8400203784cd5b45459b16ee74fa..1567d5bf3c50cc3f26706028096a7fdd1a7465a0 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -606,7 +606,8 @@ static bool conn_maxage(struct Curl_easy *data,
  * Return TRUE iff the given connection is considered dead.
  */
 bool Curl_conn_seems_dead(struct connectdata *conn,
-                          struct Curl_easy *data)
+                          struct Curl_easy *data,
+                          const struct curltime *pnow)
 {
   DEBUGASSERT(!data->conn);
   if(!CONN_INUSE(conn)) {
@@ -614,10 +615,12 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
        use */
     bool dead;
 
-    if(conn_maxage(data, conn, *Curl_pgrs_now(data))) {
+    if(conn_maxage(data, conn, *pnow)) {
       /* avoid check if already too old */
       dead = TRUE;
     }
+    else if(curlx_ptimediff_ms(pnow, &conn->lastchecked) < 1000)
+      dead = FALSE;
     else if(conn->scheme->run->connection_is_dead) {
       /* The protocol has a special method for checking the state of the
          connection. Use it to check if the connection is dead. */
@@ -625,6 +628,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
       Curl_attach_connection(data, conn);
       dead = conn->scheme->run->connection_is_dead(data, conn);
       Curl_detach_connection(data);
+      conn->lastchecked = *pnow;
     }
     else {
       bool input_pending = FALSE;
@@ -644,6 +648,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
         dead = TRUE;
       }
       Curl_detach_connection(data);
+      conn->lastchecked = *pnow;
     }
 
     if(dead) {
@@ -690,6 +695,7 @@ struct url_conn_match {
   struct connectdata *found;
   struct Curl_easy *data;
   struct connectdata *needle;
+  struct curltime now;
   BIT(may_multiplex);
   BIT(want_ntlm_http);
   BIT(want_proxy_ntlm_http);
@@ -1172,7 +1178,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
   if(!url_match_multiplex_limits(conn, m))
     return FALSE;
 
-  if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data)) {
+  if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data, &m->now)) {
     /* remove and disconnect. */
     Curl_conn_terminate(m->data, conn, FALSE);
     return FALSE;
@@ -1227,6 +1233,7 @@ static bool url_attach_existing(struct Curl_easy *data,
   memset(&match, 0, sizeof(match));
   match.data = data;
   match.needle = needle;
+  match.now = *Curl_pgrs_now(data);
   match.may_multiplex = xfer_may_multiplex(data, needle);
 
 #ifdef USE_NTLM
index ebbe9d53c47f1f0648d65b7e7aa01568c2219a8f..02f1bd3943ab71c37f7a42b24bbb28388526dc01 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -75,7 +75,8 @@ void *Curl_conn_meta_get(struct connectdata *conn, const char *key);
  * Return TRUE iff the given connection is considered dead.
  */
 bool Curl_conn_seems_dead(struct connectdata *conn,
-                          struct Curl_easy *data);
+                          struct Curl_easy *data,
+                          const struct curltime *pnow);
 
 /**
  * Perform upkeep operations on the connection.
index 35d2c3f528230b56d9640a9806a24891516b5a2f..4666fa3658ecb910fd4581e74f5397219df2b61a 100644 (file)
@@ -305,6 +305,7 @@ struct connectdata {
   char *options; /* options string, allocated */
   struct curltime created; /* creation time */
   struct curltime lastused; /* when returned to the connection pool as idle */
+  struct curltime lastchecked; /* when last checked alive status */
 
   /* A connection can have one or two sockets and connection filters.
    * The protocol using the 2nd one is FTP for CONTROL+DATA sockets */