diff options
author | Daniel Stenberg <daniel@haxx.se> | 2024-04-30 11:07:28 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2024-05-02 09:43:30 +0200 |
commit | 5f4aaf8b66ef04208c1c2121d4b780c792303f32 (patch) | |
tree | 8ef5a5ad0ea579c207b1d0b670ef868e4edc7a3a | |
parent | 38593db4a086e5ac8052e3e94c142b69b5edee58 (diff) | |
download | curl-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.c | 30 |
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; |