]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
cfilters: fix busy loop on blocked transfers
authorStefan Eissing <stefan@eissing.org>
Tue, 19 May 2026 13:31:45 +0000 (15:31 +0200)
committerJay Satiro <raysatiro@yahoo.com>
Wed, 20 May 2026 17:51:34 +0000 (13:51 -0400)
When a transfer gets paused after the connection has been established,
any data sitting in the kernel socket buffers will no longer get read.

Prevent the sockets form being added to the pollsets, because they
will trigger POLLIN endlessly and cause a busy poll loop. Same in event
based processing.

Reported-by: Harry Sintonen
Fixes https://github.com/curl/curl/issues/21671
Closes https://github.com/curl/curl/pull/21675

lib/cfilters.c

index f287ebfc7421a49e2af5d8bc098e278ea828bb2a..6f5793c833c13a910d0a43191818a4b845fab830 100644 (file)
@@ -889,8 +889,19 @@ CURLcode Curl_conn_adjust_pollset(struct Curl_easy *data,
 
   DEBUGASSERT(data);
   DEBUGASSERT(conn);
-  for(i = 0; (i < 2) && !result; ++i) {
-    result = Curl_conn_cf_adjust_pollset(conn->cfilter[i], data, ps);
+  /* During connect time, connection filters may add sockets to the pollset
+   * even when the transfer neither wants to send nor receive. And those
+   * sockets, when having events, are served.
+   * Once connected however, a transfer that neither wants to send nor receive
+   * will never call the connection filters. Any sockets added by the filters
+   * will not change state and POLLIN/POLLOUT events will trigger forever,
+   * making us busy loop. See #21671 */
+  if(ps->n || !Curl_conn_is_connected(conn, FIRSTSOCKET) ||
+     (conn->cfilter[SECONDARYSOCKET] &&
+      !Curl_conn_is_connected(conn, SECONDARYSOCKET))) {
+    for(i = 0; (i < 2) && !result && conn; ++i) {
+      result = Curl_conn_cf_adjust_pollset(conn->cfilter[i], data, ps);
+    }
   }
   return result;
 }