9d7d3f
From d3036f34cce421990e8268ee4bbfc0d9f5ceb054 Mon Sep 17 00:00:00 2001
9d7d3f
From: Daniel Stenberg <daniel@haxx.se>
9d7d3f
Date: Thu, 13 Jun 2013 19:27:12 +0200
9d7d3f
Subject: [PATCH] curl_easy_perform: avoid busy-looping
9d7d3f
9d7d3f
When curl_multi_wait() finds no file descriptor to wait for, it returns
9d7d3f
instantly and this must be handled gracefully within curl_easy_perform()
9d7d3f
or cause a busy-loop. Starting now, repeated fast returns without any
9d7d3f
file descriptors is detected and a gradually increasing sleep will be
9d7d3f
used (up to a max of 1000 milliseconds) before continuing the loop.
9d7d3f
9d7d3f
Bug: http://curl.haxx.se/bug/view.cgi?id=1238
9d7d3f
Reported-by: Miguel Angel
9d7d3f
9d7d3f
[upstream commit 0feeab7802dd2a6465d22d153d8d36b2cca99b96]
9d7d3f
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 lib/easy.c |   25 +++++++++++++++++++++++++
9d7d3f
 1 files changed, 25 insertions(+), 0 deletions(-)
9d7d3f
9d7d3f
diff --git a/lib/easy.c b/lib/easy.c
9d7d3f
index 2739598..a7051dd 100644
9d7d3f
--- a/lib/easy.c
9d7d3f
+++ b/lib/easy.c
9d7d3f
@@ -410,6 +410,9 @@ CURLcode curl_easy_perform(CURL *easy)
9d7d3f
   bool done = FALSE;
9d7d3f
   int rc;
9d7d3f
   struct SessionHandle *data = easy;
9d7d3f
+  int without_fds = 0;  /* count number of consecutive returns from
9d7d3f
+                           curl_multi_wait() without any filedescriptors */
9d7d3f
+  struct timeval before;
9d7d3f
 
9d7d3f
   if(!easy)
9d7d3f
     return CURLE_BAD_FUNCTION_ARGUMENT;
9d7d3f
@@ -445,6 +448,7 @@ CURLcode curl_easy_perform(CURL *easy)
9d7d3f
     int still_running;
9d7d3f
     int ret;
9d7d3f
 
9d7d3f
+    before = curlx_tvnow();
9d7d3f
     mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret;;
9d7d3f
 
9d7d3f
     if(mcode == CURLM_OK) {
9d7d3f
@@ -453,6 +457,27 @@ CURLcode curl_easy_perform(CURL *easy)
9d7d3f
         code = CURLE_RECV_ERROR;
9d7d3f
         break;
9d7d3f
       }
9d7d3f
+      else if(ret == 0) {
9d7d3f
+        struct timeval after = curlx_tvnow();
9d7d3f
+        /* If it returns without any filedescriptor instantly, we need to
9d7d3f
+           avoid busy-looping during periods where it has nothing particular
9d7d3f
+           to wait for */
9d7d3f
+        if(curlx_tvdiff(after, before) <= 10) {
9d7d3f
+          without_fds++;
9d7d3f
+          if(without_fds > 2) {
9d7d3f
+            int sleep_ms = without_fds * 50;
9d7d3f
+            if(sleep_ms > 1000)
9d7d3f
+              sleep_ms = 1000;
9d7d3f
+            Curl_wait_ms(sleep_ms);
9d7d3f
+          }
9d7d3f
+        }
9d7d3f
+        else
9d7d3f
+          /* it wasn't "instant", restart counter */
9d7d3f
+          without_fds = 0;
9d7d3f
+      }
9d7d3f
+      else
9d7d3f
+        /* got file descriptor, restart counter */
9d7d3f
+        without_fds = 0;
9d7d3f
 
9d7d3f
       mcode = curl_multi_perform(multi, &still_running);
9d7d3f
     }
9d7d3f
-- 
9d7d3f
1.7.1
9d7d3f