]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
connection: terminate after goaway
authorStefan Eissing <stefan@eissing.org>
Thu, 10 Jul 2025 10:16:40 +0000 (12:16 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 27 Jul 2025 20:49:12 +0000 (22:49 +0200)
When a multiplex connection (h2/h3) is shutdown by the server, the
reported number of parallel transfers allowed drops to 0.

Determine that when the last transfer is done and terminate the
connection instead of keeping it in the cache.

We detect the drop to 0 also when we try to reuse such a connection, but
if we know this at the time the last transfer is done, we better
terminate it right away.

Have a consistent trace logging to this with the connections current
hostname and port. Adjust test expectations to carry port numbers.

Closes #17884

lib/cfilters.c
lib/multi.c
tests/data/test1506
tests/data/test1510
tests/data/test1542
tests/data/test2402
tests/data/test2404
tests/data/test2502

index 01f1e282183f31079a019081eb0daffb455db8c0..6326f79f786cbbadbf53fddcb77823374a85ef7a 100644 (file)
@@ -972,12 +972,15 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
                                     int sockindex)
 {
   CURLcode result;
-  int n = 0;
+  int n = -1;
 
   struct Curl_cfilter *cf = conn->cfilter[sockindex];
   result = cf ? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
                                &n, NULL) : CURLE_UNKNOWN_OPTION;
-  return (result || n <= 0) ? 1 : (size_t)n;
+  /* If no filter answered the query, the default is a non-multiplexed
+   * connection with limit 1. Otherwise, the the query may return 0
+   * for connections that are in shutdown, e.g. server HTTP/2 GOAWAY. */
+  return (result || n < 0) ? 1 : (size_t)n;
 }
 
 int Curl_conn_get_stream_error(struct Curl_easy *data,
index 8543bfa8e5e999da18b3849472319cd0ce9f9eda..b7f16a81c33b63be5c67b3b4c416293e27ef9438 100644 (file)
@@ -535,6 +535,22 @@ static void multi_done_locked(struct connectdata *conn,
                               void *userdata)
 {
   struct multi_done_ctx *mdctx = userdata;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+  const char *host =
+#ifndef CURL_DISABLE_PROXY
+        conn->bits.socksproxy ?
+        conn->socks_proxy.host.dispname :
+        conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+#endif
+        conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+        conn->host.dispname;
+  int port =
+#ifndef CURL_DISABLE_PROXY
+        conn->bits.httpproxy ? conn->http_proxy.port :
+#endif
+        conn->bits.conn_to_port ? conn->conn_to_port :
+        conn->remote_port;
+#endif
 
   Curl_detach_connection(data);
 
@@ -580,30 +596,27 @@ static void multi_done_locked(struct connectdata *conn,
 #endif
      ) || conn->bits.close
        || (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
-    CURL_TRC_M(data, "multi_done, not reusing connection=%"
-                     FMT_OFF_T ", forbid=%d"
-                     ", close=%d, premature=%d, conn_multiplex=%d",
-                     conn->connection_id, data->set.reuse_forbid,
-                     conn->bits.close, mdctx->premature,
-                     Curl_conn_is_multiplex(conn, FIRSTSOCKET));
+    CURL_TRC_M(data, "multi_done, terminating conn #%" FMT_OFF_T " to %s:%d, "
+               "forbid=%d, close=%d, premature=%d, conn_multiplex=%d",
+               conn->connection_id, host, port, data->set.reuse_forbid,
+               conn->bits.close, mdctx->premature,
+               Curl_conn_is_multiplex(conn, FIRSTSOCKET));
     connclose(conn, "disconnecting");
     Curl_conn_terminate(data, conn, mdctx->premature);
   }
+  else if(!Curl_conn_get_max_concurrent(data, conn, FIRSTSOCKET)) {
+    CURL_TRC_M(data, "multi_done, conn #%" FMT_OFF_T " to %s:%d was shutdown"
+               " by server, not reusing", conn->connection_id, host, port);
+    connclose(conn, "server shutdown");
+    Curl_conn_terminate(data, conn, mdctx->premature);
+  }
   else {
     /* the connection is no longer in use by any transfer */
     if(Curl_cpool_conn_now_idle(data, conn)) {
       /* connection kept in the cpool */
-      const char *host =
-#ifndef CURL_DISABLE_PROXY
-        conn->bits.socksproxy ?
-        conn->socks_proxy.host.dispname :
-        conn->bits.httpproxy ? conn->http_proxy.host.dispname :
-#endif
-        conn->bits.conn_to_host ? conn->conn_to_host.dispname :
-        conn->host.dispname;
       data->state.lastconnect_id = conn->connection_id;
-      infof(data, "Connection #%" FMT_OFF_T " to host %s left intact",
-            conn->connection_id, host);
+      infof(data, "Connection #%" FMT_OFF_T " to host %s:%d left intact",
+            conn->connection_id, host, port);
     }
     else {
       /* connection was removed from the cpool and destroyed. */
index 90f1ed421c4763576aa8da3bfc7ec87edb8ae41f..d3cec057808b11c732024b1a3844f756482df664 100644 (file)
@@ -83,10 +83,10 @@ Accept: */*
 ^Host:.*
 </strip>
 <file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
-* Connection #0 to host server1.example.com left intact
-* Connection #1 to host server2.example.com left intact
-* Connection #2 to host server3.example.com left intact
-* Connection #3 to host server4.example.com left intact
+* Connection #0 to host server1.example.com:%HTTPPORT left intact
+* Connection #1 to host server2.example.com:%HTTPPORT left intact
+* Connection #2 to host server3.example.com:%HTTPPORT left intact
+* Connection #3 to host server4.example.com:%HTTPPORT left intact
 </file>
 <stripfile>
 $_ = '' if(($_ !~ /left intact/) && ($_ !~ /Closing connection/))
index 23ef9517c99a671f8a3ab480405f6c8919db546f..236fbde3d90a2bbcb73d78965ec5a99b2f9f4c21 100644 (file)
@@ -83,10 +83,10 @@ Accept: */*
 ^Host:.*
 </strip>
 <file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
-* Connection #0 to host server1.example.com left intact
-* Connection #1 to host server2.example.com left intact
-* Connection #2 to host server3.example.com left intact
-* Connection #3 to host server4.example.com left intact
+* Connection #0 to host server1.example.com:%HTTPPORT left intact
+* Connection #1 to host server2.example.com:%HTTPPORT left intact
+* Connection #2 to host server3.example.com:%HTTPPORT left intact
+* Connection #3 to host server4.example.com:%HTTPPORT left intact
 </file>
 <stripfile>
 $_ = '' if(($_ !~ /left intact/) && ($_ !~ /Closing connection/))
index 25df4a46e335e38fe10630e64c6ceedc62aa3ad7..656af421dfd3bbccf5d5d09e291213ca22b99d17 100644 (file)
@@ -55,11 +55,11 @@ Accept: */*
 \r
 </protocol>
 <file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
-== Info: Connection #0 to host %HOSTIP left intact
-== Info: Connection #0 to host %HOSTIP left intact
-== Info: Connection #0 to host %HOSTIP left intact
+== Info: Connection #0 to host %HOSTIP:%HTTPPORT left intact
+== Info: Connection #0 to host %HOSTIP:%HTTPPORT left intact
+== Info: Connection #0 to host %HOSTIP:%HTTPPORT left intact
 == Info: shutting down connection #0
-== Info: Connection #1 to host %HOSTIP left intact
+== Info: Connection #1 to host %HOSTIP:%HTTPPORT left intact
 </file>
 <stripfile>
 $_ = '' if(($_ !~ /left intact/) && ($_ !~ /(closing|shutting down) connection #\d+/))
index 52c582415f6d6e39a96f6efa96793881e9916c2e..563443171aecad819814ba51a1725a8cd4c01480 100644 (file)
@@ -96,10 +96,10 @@ Via: 2 nghttpx
 ^Host:.*
 </strip>
 <file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
-* Connection #0 to host localhost left intact
-* Connection #0 to host localhost left intact
-* Connection #0 to host localhost left intact
-* Connection #0 to host localhost left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
 </file>
 <stripfile>
 $_ = '' if(($_ !~ /left intact/) && ($_ !~ /Closing connection/))
index e7d68299cec17451217930f62b16d4ae559c472a..4ebcceac812943f830125cb7e875f5defe1dede6 100644 (file)
@@ -96,10 +96,10 @@ Via: 2 nghttpx
 ^Host:.*
 </strip>
 <file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
-* Connection #0 to host localhost left intact
-* Connection #0 to host localhost left intact
-* Connection #0 to host localhost left intact
-* Connection #0 to host localhost left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
+* Connection #0 to host localhost:%HTTP2TLSPORT left intact
 </file>
 <stripfile>
 $_ = '' if(($_ !~ /left intact/) && ($_ !~ /Closing connection/))
index e86e6125ad92117f74a0bb68684e1b4d906afedb..311b23deffbcd42da87de047debb7f652ecd1d0d 100644 (file)
@@ -91,10 +91,10 @@ Via: 3 nghttpx
 ^Host:.*
 </strip>
 <file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
-== Info: Connection #0 to host localhost left intact
-== Info: Connection #0 to host localhost left intact
-== Info: Connection #0 to host localhost left intact
-== Info: Connection #0 to host localhost left intact
+== Info: Connection #0 to host localhost:%HTTP3PORT left intact
+== Info: Connection #0 to host localhost:%HTTP3PORT left intact
+== Info: Connection #0 to host localhost:%HTTP3PORT left intact
+== Info: Connection #0 to host localhost:%HTTP3PORT left intact
 </file>
 <stripfile>
 $_ = '' if(($_ !~ /left intact/) && ($_ !~ /Closing connection/))