summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2013-06-13 19:27:12 +0200
committerDaniel Stenberg <daniel@haxx.se>2013-06-13 19:27:12 +0200
commit0feeab7802dd2a6465d22d153d8d36b2cca99b96 (patch)
tree2c830a356ee4e24e6eb9414958a953ffa7d14875
parentf24dc09d209a2f91ca38d854f0c15ad93f3d7e2d (diff)
downloadgnurl-0feeab7802dd2a6465d22d153d8d36b2cca99b96.tar.gz
gnurl-0feeab7802dd2a6465d22d153d8d36b2cca99b96.tar.bz2
gnurl-0feeab7802dd2a6465d22d153d8d36b2cca99b96.zip
curl_easy_perform: avoid busy-looping
When curl_multi_wait() finds no file descriptor to wait for, it returns instantly and this must be handled gracefully within curl_easy_perform() or cause a busy-loop. Starting now, repeated fast returns without any file descriptors is detected and a gradually increasing sleep will be used (up to a max of 1000 milliseconds) before continuing the loop. Bug: http://curl.haxx.se/bug/view.cgi?id=1238 Reported-by: Miguel Angel
-rw-r--r--lib/easy.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/lib/easy.c b/lib/easy.c
index 5d441f718..94a84abb2 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -420,6 +420,9 @@ CURLcode curl_easy_perform(CURL *easy)
bool done = FALSE;
int rc;
struct SessionHandle *data = easy;
+ int without_fds = 0; /* count number of consecutive returns from
+ curl_multi_wait() without any filedescriptors */
+ struct timeval before;
if(!easy)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -460,6 +463,7 @@ CURLcode curl_easy_perform(CURL *easy)
int still_running;
int ret;
+ before = curlx_tvnow();
mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
if(mcode == CURLM_OK) {
@@ -468,6 +472,27 @@ CURLcode curl_easy_perform(CURL *easy)
code = CURLE_RECV_ERROR;
break;
}
+ else if(ret == 0) {
+ struct timeval after = curlx_tvnow();
+ /* If it returns without any filedescriptor instantly, we need to
+ avoid busy-looping during periods where it has nothing particular
+ to wait for */
+ if(curlx_tvdiff(after, before) <= 10) {
+ without_fds++;
+ if(without_fds > 2) {
+ int sleep_ms = without_fds * 50;
+ if(sleep_ms > 1000)
+ sleep_ms = 1000;
+ Curl_wait_ms(sleep_ms);
+ }
+ }
+ else
+ /* it wasn't "instant", restart counter */
+ without_fds = 0;
+ }
+ else
+ /* got file descriptor, restart counter */
+ without_fds = 0;
mcode = curl_multi_perform(multi, &still_running);
}