From 00cac453c7955d8a3894772e02029bb8b65a2c12 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Wed, 22 Apr 2026 15:00:14 +0200 Subject: [PATCH] multi: enhance pending handles fairness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 | 23 +++++++++++++++++++++-- lib/multihandle.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/multi.c b/lib/multi.c index f3fd7938fb..7520253d70 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -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); diff --git a/lib/multihandle.h b/lib/multihandle.h index a0519889ab..c5cdfbe82e 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -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 */