aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2024-04-30 11:07:28 +0200
committerDaniel Stenberg <daniel@haxx.se>2024-05-02 09:43:30 +0200
commit5f4aaf8b66ef04208c1c2121d4b780c792303f32 (patch)
tree8ef5a5ad0ea579c207b1d0b670ef868e4edc7a3a
parent38593db4a086e5ac8052e3e94c142b69b5edee58 (diff)
downloadcurl-5f4aaf8b66ef04208c1c2121d4b780c792303f32.tar.gz
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
-rw-r--r--src/tool_cb_rea.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c
index 8cb5bbe8a..961dd113b 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;