From 5e4e62962c0f8536c612a5248e2ac4eb7d67ae66 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Tue, 19 May 2026 15:31:45 +0200 Subject: [PATCH] cfilters: fix busy loop on blocked transfers 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 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/cfilters.c b/lib/cfilters.c index f287ebfc74..6f5793c833 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -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; }