From eb6d1e098e98f6e15cb8fdd24f87419bd7a8787f Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Mon, 15 Jun 2026 10:19:56 +0200 Subject: [PATCH] ratelimits: use minimal burst rate Some protocols (and servers) prefer to batch IO and will not send data unless the window is of sufficient size. Set the burst rate for our rate limits to a minimum of 32KB to prevent stalling. Reported-by: Tatsuhiro Tsujikawa Closes #22016 --- lib/ratelimit.c | 8 +++++--- lib/setopt.c | 8 ++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/ratelimit.c b/lib/ratelimit.c index dc013757e9..97af01c788 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c @@ -141,12 +141,14 @@ static void rlimit_tune_steps(struct Curl_rlimit *r, r->step_us = CURL_US_PER_SEC + ((timediff_t)mstep_inc * 1000); r->rate_per_step += rate_inc; r->tokens = r->rate_per_step; + if(r->burst_per_step) { + curl_off_t burst_inc = ((r->burst_per_step * mstep_inc) / 1000); + if(burst_inc) + r->burst_per_step += burst_inc; + } } } } - - if(r->burst_per_step) - r->burst_per_step = r->rate_per_step; } void Curl_rlimit_init(struct Curl_rlimit *r, diff --git a/lib/setopt.c b/lib/setopt.c index e2e30622f1..e56d69129e 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2768,7 +2768,9 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option, if(offt < 0) return CURLE_BAD_FUNCTION_ARGUMENT; s->max_send_speed = offt; - Curl_rlimit_init(&data->progress.ul.rlimit, offt, offt, + /* use minimal burst rate of 32k. some protocol batch IO */ + Curl_rlimit_init(&data->progress.ul.rlimit, offt, + CURLMAX(offt, (32 * 1024)), Curl_pgrs_now(data)); break; case CURLOPT_MAX_RECV_SPEED_LARGE: @@ -2779,7 +2781,9 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option, if(offt < 0) return CURLE_BAD_FUNCTION_ARGUMENT; s->max_recv_speed = offt; - Curl_rlimit_init(&data->progress.dl.rlimit, offt, offt, + /* use minimal burst rate of 32k. some protocol batch IO */ + Curl_rlimit_init(&data->progress.dl.rlimit, offt, + CURLMAX(offt, (32 * 1024)), Curl_pgrs_now(data)); break; case CURLOPT_RESUME_FROM_LARGE: