diff options
author | Daniel Stenberg <daniel@haxx.se> | 2019-06-08 23:03:03 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2019-06-09 18:33:59 +0200 |
commit | 680f1413321c0bad593a69a86511df4d98a3b5df (patch) | |
tree | 500ec23c0a46693f449e3ed4758281dd36cb3f92 | |
parent | cf1ec70e721544ba39652abd6331dde6bbf9108d (diff) |
unpause: trigger a timeout for event-based transfers
... so that timeouts or other state machine actions get going again
after a changing pause state. For example, if the last delivery was
paused there's no pending socket activity.
Reported-by: sstruchtrup on github
Fixes #3994
Closes #4001
-rw-r--r-- | lib/easy.c | 5 | ||||
-rw-r--r-- | lib/multi.c | 52 | ||||
-rw-r--r-- | lib/multiif.h | 1 |
3 files changed, 31 insertions, 27 deletions
diff --git a/lib/easy.c b/lib/easy.c index 4a6f96567..a4fff5b36 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -1038,8 +1038,11 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) to have this handle checked soon */ if(!result && ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != - (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) + (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) { Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ + if(data->multi) + Curl_update_timer(data->multi); + } /* This transfer may have been moved in or out of the bundle, update the corresponding socket callback, if used */ diff --git a/lib/multi.c b/lib/multi.c index 02f846033..dc780630b 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -71,8 +71,6 @@ static CURLMcode singlesocket(struct Curl_multi *multi, struct Curl_easy *data); -static int update_timer(struct Curl_multi *multi); - static CURLMcode add_next_timeout(struct curltime now, struct Curl_multi *multi, struct Curl_easy *d); @@ -462,16 +460,16 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, /* increase the alive-counter */ multi->num_alive++; - /* A somewhat crude work-around for a little glitch in update_timer() that - happens if the lastcall time is set to the same time when the handle is - removed as when the next handle is added, as then the check in - update_timer() that prevents calling the application multiple times with - the same timer info will not trigger and then the new handle's timeout - will not be notified to the app. + /* A somewhat crude work-around for a little glitch in Curl_update_timer() + that happens if the lastcall time is set to the same time when the handle + is removed as when the next handle is added, as then the check in + Curl_update_timer() that prevents calling the application multiple times + with the same timer info will not trigger and then the new handle's + timeout will not be notified to the app. The work-around is thus simply to clear the 'lastcall' variable to force - update_timer() to always trigger a callback to the app when a new easy - handle is added */ + Curl_update_timer() to always trigger a callback to the app when a new + easy handle is added */ memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); /* The closure handle only ever has default timeouts set. To improve the @@ -484,7 +482,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->state.conn_cache->closure_handle->set.no_signal = data->set.no_signal; - update_timer(multi); + Curl_update_timer(multi); return CURLM_OK; } @@ -774,7 +772,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, We do not touch the easy handle here! */ multi->num_easy--; /* one less to care about now */ - update_timer(multi); + Curl_update_timer(multi); return CURLM_OK; } @@ -2107,7 +2105,7 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) *running_handles = multi->num_alive; if(CURLM_OK >= returncode) - update_timer(multi); + Curl_update_timer(multi); return returncode; } @@ -2544,9 +2542,10 @@ static CURLMcode multi_socket(struct Curl_multi *multi, } else { /* Asked to run due to time-out. Clear the 'lastcall' variable to force - update_timer() to trigger a callback to the app again even if the same - timeout is still the one to run after this call. That handles the case - when the application asks libcurl to run the timeout prematurely. */ + Curl_update_timer() to trigger a callback to the app again even if the + same timeout is still the one to run after this call. That handles the + case when the application asks libcurl to run the timeout + prematurely. */ memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); } @@ -2664,7 +2663,7 @@ CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s, return CURLM_RECURSIVE_API_CALL; result = multi_socket(multi, FALSE, s, 0, running_handles); if(CURLM_OK >= result) - update_timer(multi); + Curl_update_timer(multi); return result; } @@ -2676,7 +2675,7 @@ CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s, return CURLM_RECURSIVE_API_CALL; result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles); if(CURLM_OK >= result) - update_timer(multi); + Curl_update_timer(multi); return result; } @@ -2688,7 +2687,7 @@ CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles) return CURLM_RECURSIVE_API_CALL; result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles); if(CURLM_OK >= result) - update_timer(multi); + Curl_update_timer(multi); return result; } @@ -2748,14 +2747,14 @@ CURLMcode curl_multi_timeout(struct Curl_multi *multi, * Tell the application it should update its timers, if it subscribes to the * update timer callback. */ -static int update_timer(struct Curl_multi *multi) +void Curl_update_timer(struct Curl_multi *multi) { long timeout_ms; if(!multi->timer_cb) - return 0; + return; if(multi_timeout(multi, &timeout_ms)) { - return -1; + return; } if(timeout_ms < 0) { static const struct curltime none = {0, 0}; @@ -2763,9 +2762,10 @@ static int update_timer(struct Curl_multi *multi) multi->timer_lastcall = none; /* there's no timeout now but there was one previously, tell the app to disable it */ - return multi->timer_cb(multi, -1, multi->timer_userp); + multi->timer_cb(multi, -1, multi->timer_userp); + return; } - return 0; + return; } /* When multi_timeout() is done, multi->timetree points to the node with the @@ -2773,11 +2773,11 @@ static int update_timer(struct Curl_multi *multi) * if this is the same (fixed) time as we got in a previous call and then * avoid calling the callback again. */ if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0) - return 0; + return; multi->timer_lastcall = multi->timetree->key; - return multi->timer_cb(multi, timeout_ms, multi->timer_userp); + multi->timer_cb(multi, timeout_ms, multi->timer_userp); } /* diff --git a/lib/multiif.h b/lib/multiif.h index e8a5e7062..55297ea51 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -30,6 +30,7 @@ void Curl_updatesocket(struct Curl_easy *data); void Curl_expire(struct Curl_easy *data, time_t milli, expire_id); void Curl_expire_clear(struct Curl_easy *data); void Curl_expire_done(struct Curl_easy *data, expire_id id); +void Curl_update_timer(struct Curl_multi *multi); void Curl_detach_connnection(struct Curl_easy *data); void Curl_attach_connnection(struct Curl_easy *data, struct connectdata *conn); |