diff options
author | Daniel Stenberg <daniel@haxx.se> | 2013-06-13 19:27:12 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2013-06-13 19:27:12 +0200 |
commit | 0feeab7802dd2a6465d22d153d8d36b2cca99b96 (patch) | |
tree | 2c830a356ee4e24e6eb9414958a953ffa7d14875 /lib | |
parent | f24dc09d209a2f91ca38d854f0c15ad93f3d7e2d (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/easy.c | 25 |
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); } |