From: Daniel Stenberg Date: Tue, 30 Apr 2024 09:07:28 +0000 (+0200) Subject: tool_cb_rea: limit rate unpause for -T . uploads X-Git-Tag: curl-8_8_0~134 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f4aaf8b66ef04208c1c2121d4b780c792303f32;p=thirdparty%2Fcurl.git tool_cb_rea: limit rate unpause for -T . uploads To avoid getting stuck in a busy-loop when nothing is read from stdin, this function now checks the call rate and might enforce a short sleep when called repeatedly without uploading anything. It is a crude work-around to avoid a 100% busy CPU. Reported-by: magisterquis on hackerone Fixes #13174 Closes #13506 --- diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c index 8cb5bbe8ac..961dd113bc 100644 --- a/src/tool_cb_rea.c +++ b/src/tool_cb_rea.c @@ -36,6 +36,7 @@ #include "tool_operate.h" #include "tool_util.h" #include "tool_msgs.h" +#include "tool_sleep.h" #include "memdebug.h" /* keep this as LAST include */ @@ -124,8 +125,33 @@ int tool_readbusy_cb(void *clientp, (void)ulnow; /* unused */ if(config->readbusy) { - config->readbusy = FALSE; - curl_easy_pause(per->curl, CURLPAUSE_CONT); + /* lame code to keep the rate down because the input might not deliver + anything, get paused again and come back here immediately */ + static long rate = 500; + static struct timeval prev; + static curl_off_t ulprev; + + if(ulprev == ulnow) { + /* it did not upload anything since last call */ + struct timeval now = tvnow(); + if(prev.tv_sec) + /* get a rolling average rate */ + /* rate = rate - rate/4 + tvdiff(now, prev)/4; */ + rate -= rate/4 - tvdiff(now, prev)/4; + prev = now; + } + else { + rate = 50; + ulprev = ulnow; + } + if(rate >= 50) { + /* keeps the looping down to 20 times per second in the crazy case */ + config->readbusy = FALSE; + curl_easy_pause(per->curl, CURLPAUSE_CONT); + } + else + /* sleep half a period */ + tool_go_sleep(25); } return per->noprogress? 0 : CURL_PROGRESSFUNC_CONTINUE;