]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ratelimit blocking: fix busy loop
authorStefan Eissing <stefan@eissing.org>
Mon, 29 Dec 2025 10:21:31 +0000 (11:21 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 29 Dec 2025 21:44:34 +0000 (22:44 +0100)
Fix the pollset in perform state to not add sockets for directions
that are blocked. This otherwise will lead to busy loops for a
transfer that cannot be progressed.

Reported-by: Fizn-Ahmd on github
Fixes #20091
Closes #20109

lib/multi.c
lib/request.c
lib/request.h

index 92f6ca764dc39fc16ccd124760660ac979440b1e..aec0739c39c4de97fcaac155ebef0a63bad5c45a 100644 (file)
@@ -1080,10 +1080,9 @@ static CURLcode mstate_perform_pollset(struct Curl_easy *data,
     result = conn->handler->perform_pollset(data, ps);
   else {
     /* Default is to obey the data->req.keepon flags for send/recv */
-    if(CURL_WANT_RECV(data) && CONN_SOCK_IDX_VALID(conn->recv_idx)) {
+    if(Curl_req_want_recv(data) && CONN_SOCK_IDX_VALID(conn->recv_idx)) {
       result = Curl_pollset_add_in(data, ps, conn->sock[conn->recv_idx]);
     }
-
     if(!result && Curl_req_want_send(data) &&
        CONN_SOCK_IDX_VALID(conn->send_idx)) {
       result = Curl_pollset_add_out(data, ps, conn->sock[conn->send_idx]);
index 90c10af99c4ef5055a8d15c493969151bc2a7481..ad7f628f1ac3da921e11b680f77cdd5184174ef3 100644 (file)
@@ -415,16 +415,25 @@ bool Curl_req_sendbuf_empty(struct Curl_easy *data)
 
 bool Curl_req_want_send(struct Curl_easy *data)
 {
-  /* Not done and
-   * - KEEP_SEND and not PAUSEd.
-   * - or request has buffered data to send
-   * - or transfer connection has pending data to send */
+  /* Not done and upload not blocked and either one of
+   * - KEEP_SEND
+   * - request has buffered data to send
+   * - connection has pending data to send */
   return !data->req.done &&
+         !Curl_rlimit_is_blocked(&data->progress.ul.rlimit) &&
          ((data->req.keepon & KEEP_SEND) ||
           !Curl_req_sendbuf_empty(data) ||
           Curl_xfer_needs_flush(data));
 }
 
+bool Curl_req_want_recv(struct Curl_easy *data)
+{
+  /* Not done and download not blocked and KEEP_RECV */
+  return !data->req.done &&
+         !Curl_rlimit_is_blocked(&data->progress.dl.rlimit) &&
+         (data->req.keepon & KEEP_RECV);
+}
+
 bool Curl_req_done_sending(struct Curl_easy *data)
 {
   return data->req.upload_done && !Curl_req_want_send(data);
index 0b006dc77ce45b845dd981c62e777be7205f6c53..389ae4d8b1f8d7d6db078637f29304f6e5cf36a7 100644 (file)
@@ -193,11 +193,13 @@ bool Curl_req_done_sending(struct Curl_easy *data);
  */
 CURLcode Curl_req_send_more(struct Curl_easy *data);
 
-/**
- * TRUE iff the request wants to send, e.g. has buffered bytes.
- */
+/* TRUE if the request wants to send, e.g. is not done sending
+ * and is not blocked. */
 bool Curl_req_want_send(struct Curl_easy *data);
 
+/* TRUE if the request wants to receive and is not blocked. */
+bool Curl_req_want_recv(struct Curl_easy *data);
+
 /**
  * TRUE iff the request has no buffered bytes yet to send.
  */