]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: enhance pending handles fairness
authorStefan Eissing <stefan@eissing.org>
Wed, 22 Apr 2026 13:00:14 +0000 (15:00 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 23 Apr 2026 13:55:07 +0000 (15:55 +0200)
When trying to connect a pending transfer, remember the `mid` that was
last reactivated and start looking for future pending handles from the
last one forward through the pending bitset.

Background: when many pending handles exist, iterating the bitset always
from the start may become unfair to transfers that were assigned higher
`mid` values.

Fixes #21396
Reported-by: Juan Belón
Closes #21412

lib/multi.c
lib/multihandle.h

index f3fd7938fbe0bf7aaccfe66cd297216be40e3331..7520253d702c108c96e26d1b2e123586bac3a243 100644 (file)
@@ -3760,13 +3760,32 @@ static void move_pending_to_connect(struct Curl_multi *multi,
 */
 static void process_pending_handles(struct Curl_multi *multi)
 {
-  uint32_t mid;
+  uint32_t mid = multi->last_pending_mid;
+
+  if(mid) {
+    while(Curl_uint32_bset_next(&multi->pending, mid, &mid)) {
+      struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+      if(data) {
+        move_pending_to_connect(multi, data);
+        multi->last_pending_mid = mid;
+        return;
+      }
+      /* transfer no longer known, should not happen */
+      Curl_uint32_bset_remove(&multi->pending, mid);
+      DEBUGASSERT(0);
+    }
+    /* found no pending transfers with `mid` larger than `last_pending_mid`.
+     * Start at the beginning of the pending set again. */
+    multi->last_pending_mid = 0;
+  }
+
   if(Curl_uint32_bset_first(&multi->pending, &mid)) {
     do {
       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
       if(data) {
         move_pending_to_connect(multi, data);
-        break;
+        multi->last_pending_mid = mid;
+        return;
       }
       /* transfer no longer known, should not happen */
       Curl_uint32_bset_remove(&multi->pending, mid);
index a0519889ab4da20c3f6100a0ff15a0f39e46b38c..c5cdfbe82e42df20f963e03e1e65dda5f5a5602d 100644 (file)
@@ -175,6 +175,7 @@ struct Curl_multi {
 #ifdef DEBUGBUILD
   unsigned int now_access_count;
 #endif
+  uint32_t last_pending_mid; /* mid of last pending transfer rescheduled */
   uint32_t last_resolv_id; /* id of the last DNS resolve operation */
   BIT(ipv6_works);
   BIT(multiplexing);           /* multiplexing wanted */