diff options
author | Daniel Stenberg <daniel@haxx.se> | 2019-07-29 13:41:00 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2019-08-06 09:33:29 +0200 |
commit | 02346abc32a3995299fa9c2f35b9f0a1d091b045 (patch) | |
tree | de504a328c326fc2ebef7265ddf4de7456fd56be /lib/multi.c | |
parent | cee7639b790f29113759f69c4a955c2ead8bff31 (diff) | |
download | curl-02346abc32a3995299fa9c2f35b9f0a1d091b045.tar.gz |
curl_multi_poll: a sister to curl_multi_wait() that waits more
Repeatedly we see problems where using curl_multi_wait() is difficult or
just awkward because if it has no file descriptor to wait for
internally, it returns immediately and leaves it to the caller to wait
for a small amount of time in order to avoid occasional busy-looping.
This is often missed or misunderstood, leading to underperforming
applications.
This change introduces curl_multi_poll() as a replacement drop-in
function that accepts the exact same set of arguments. This function
works identically to curl_multi_wait() - EXCEPT - for the case when
there's nothing to wait for internally, as then this function will by
itself wait for a "suitable" short time before it returns. This
effectiely avoids all risks of busy-looping and should also make it less
likely that apps "over-wait".
This also changes the curl tool to use this funtion internally when
doing parallel transfers and changes curl_easy_perform() to use it
internally.
Closes #4163
Diffstat (limited to 'lib/multi.c')
-rwxr-xr-x | lib/multi.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/lib/multi.c b/lib/multi.c index 6e16eafe0..e5c483c56 100755 --- a/lib/multi.c +++ b/lib/multi.c @@ -974,12 +974,12 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, #define NUM_POLLS_ON_STACK 10 -CURLMcode Curl_multi_wait(struct Curl_multi *multi, - struct curl_waitfd extra_fds[], - unsigned int extra_nfds, - int timeout_ms, - int *ret, - bool *gotsocket) /* if any socket was checked */ +static CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool extrawait) /* when no socket, wait */ { struct Curl_easy *data; curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; @@ -993,9 +993,6 @@ CURLMcode Curl_multi_wait(struct Curl_multi *multi, struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; struct pollfd *ufds = &a_few_on_stack[0]; - if(gotsocket) - *gotsocket = FALSE; - if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -1124,9 +1121,19 @@ CURLMcode Curl_multi_wait(struct Curl_multi *multi, free(ufds); if(ret) *ret = retcode; - if(gotsocket && (extra_fds || curlfds)) + if(!extrawait || extra_fds || curlfds) /* if any socket was checked */ - *gotsocket = TRUE; + ; + else { + long sleep_ms = 0; + + /* Avoid busy-looping when there's nothing particular to wait for */ + if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) { + if(sleep_ms > timeout_ms) + sleep_ms = timeout_ms; + Curl_wait_ms((int)sleep_ms); + } + } return CURLM_OK; } @@ -1137,7 +1144,16 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, int timeout_ms, int *ret) { - return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL); + return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE); +} + +CURLMcode curl_multi_poll(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret) +{ + return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE); } /* |