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
This commit is contained in:
Stefan Eissing 2026-05-19 15:31:45 +02:00 committed by Jay Satiro
parent ba7b65f957
commit 5e4e62962c

View 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;
}