Selaa lähdekoodia

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
Daniel Stenberg 3 viikkoa sitten
vanhempi
commit
5f4aaf8b66
1 muutettua tiedostoa jossa 28 lisäystä ja 2 poistoa
  1. 28 2
      src/tool_cb_rea.c

+ 28 - 2
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;