1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

curl: retry delays in parallel mode no longer sleeps blocking

The previous sleep for retries would block all other concurrent
transfers. Starting now, the retry will instead be properly marked to
not get restarted until after the delay time but other transfers can
still continue in the mean time.

Closes #5917
This commit is contained in:
Daniel Stenberg 2020-09-05 17:44:24 +02:00
parent e4e725f835
commit 363a88ac9d
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 39 additions and 12 deletions

View File

@ -333,7 +333,8 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
static CURLcode post_per_transfer(struct GlobalConfig *global, static CURLcode post_per_transfer(struct GlobalConfig *global,
struct per_transfer *per, struct per_transfer *per,
CURLcode result, CURLcode result,
bool *retryp) bool *retryp,
long *delay) /* milliseconds! */
{ {
struct OutStruct *outs = &per->outs; struct OutStruct *outs = &per->outs;
CURL *curl = per->curl; CURL *curl = per->curl;
@ -343,6 +344,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
return result; return result;
*retryp = FALSE; *retryp = FALSE;
*delay = 0; /* for no retry, keep it zero */
if(per->infdopen) if(per->infdopen)
close(per->infd); close(per->infd);
@ -535,7 +537,6 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
m[retry], sleeptime/1000L, per->retry_numretries); m[retry], sleeptime/1000L, per->retry_numretries);
per->retry_numretries--; per->retry_numretries--;
tool_go_sleep(sleeptime);
if(!config->retry_delay) { if(!config->retry_delay) {
per->retry_sleep *= 2; per->retry_sleep *= 2;
if(per->retry_sleep > RETRY_SLEEP_MAX) if(per->retry_sleep > RETRY_SLEEP_MAX)
@ -578,7 +579,8 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
} }
outs->bytes = 0; /* clear for next round */ outs->bytes = 0; /* clear for next round */
} }
*retryp = TRUE; /* curl_easy_perform loop */ *retryp = TRUE;
*delay = sleeptime;
return CURLE_OK; return CURLE_OK;
} }
} /* if retry_numretries */ } /* if retry_numretries */
@ -2152,6 +2154,7 @@ static CURLcode add_parallel_transfers(struct GlobalConfig *global,
struct per_transfer *per; struct per_transfer *per;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
CURLMcode mcode; CURLMcode mcode;
bool sleeping = FALSE;
*addedp = FALSE; *addedp = FALSE;
*morep = FALSE; *morep = FALSE;
result = create_transfer(global, share, addedp); result = create_transfer(global, share, addedp);
@ -2163,6 +2166,11 @@ static CURLcode add_parallel_transfers(struct GlobalConfig *global,
if(per->added) if(per->added)
/* already added */ /* already added */
continue; continue;
if(per->startat && (time(NULL) < per->startat)) {
/* this is still delaying */
sleeping = TRUE;
continue;
}
result = pre_transfer(global, per); result = pre_transfer(global, per);
if(result) if(result)
@ -2187,7 +2195,7 @@ static CURLcode add_parallel_transfers(struct GlobalConfig *global,
all_added++; all_added++;
*addedp = TRUE; *addedp = TRUE;
} }
*morep = per ? TRUE : FALSE; *morep = (per || sleeping) ? TRUE : FALSE;
return CURLE_OK; return CURLE_OK;
} }
@ -2201,6 +2209,7 @@ static CURLcode parallel_transfers(struct GlobalConfig *global,
struct timeval start = tvnow(); struct timeval start = tvnow();
bool more_transfers; bool more_transfers;
bool added_transfers; bool added_transfers;
time_t tick = time(NULL);
multi = curl_multi_init(); multi = curl_multi_init();
if(!multi) if(!multi)
@ -2223,28 +2232,39 @@ static CURLcode parallel_transfers(struct GlobalConfig *global,
if(!mcode) { if(!mcode) {
int rc; int rc;
CURLMsg *msg; CURLMsg *msg;
bool removed = FALSE; bool checkmore = FALSE;
do { do {
msg = curl_multi_info_read(multi, &rc); msg = curl_multi_info_read(multi, &rc);
if(msg) { if(msg) {
bool retry; bool retry;
long delay;
struct per_transfer *ended; struct per_transfer *ended;
CURL *easy = msg->easy_handle; CURL *easy = msg->easy_handle;
result = msg->data.result; result = msg->data.result;
curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended); curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended);
curl_multi_remove_handle(multi, easy); curl_multi_remove_handle(multi, easy);
result = post_per_transfer(global, ended, result, &retry); result = post_per_transfer(global, ended, result, &retry, &delay);
progress_finalize(ended); /* before it goes away */ progress_finalize(ended); /* before it goes away */
all_added--; /* one fewer added */ all_added--; /* one fewer added */
removed = TRUE; checkmore = TRUE;
if(retry) if(retry) {
ended->added = FALSE; /* add it again */ ended->added = FALSE; /* add it again */
/* we delay retries in full integer seconds only */
ended->startat = delay ? time(NULL) + delay/1000 : 0;
}
else else
(void)del_per_transfer(ended); (void)del_per_transfer(ended);
} }
} while(msg); } while(msg);
if(removed) { if(!checkmore) {
time_t tock = time(NULL);
if(tick != tock) {
checkmore = TRUE;
tick = tock;
}
}
if(checkmore) {
/* one or more transfers completed, add more! */ /* one or more transfers completed, add more! */
(void)add_parallel_transfers(global, multi, share, (void)add_parallel_transfers(global, multi, share,
&more_transfers, &more_transfers,
@ -2284,6 +2304,7 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
return result; return result;
for(per = transfers; per;) { for(per = transfers; per;) {
bool retry; bool retry;
long delay;
bool bailout = FALSE; bool bailout = FALSE;
result = pre_transfer(global, per); result = pre_transfer(global, per);
if(result) if(result)
@ -2306,9 +2327,11 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
/* store the result of the actual transfer */ /* store the result of the actual transfer */
returncode = result; returncode = result;
result = post_per_transfer(global, per, result, &retry); result = post_per_transfer(global, per, result, &retry, &delay);
if(retry) if(retry) {
tool_go_sleep(delay);
continue; continue;
}
/* Bail out upon critical errors or --fail-early */ /* Bail out upon critical errors or --fail-early */
if(result || is_fatal_error(returncode) || if(result || is_fatal_error(returncode) ||
@ -2483,7 +2506,8 @@ static CURLcode run_all_transfers(struct GlobalConfig *global,
/* cleanup if there are any left */ /* cleanup if there are any left */
for(per = transfers; per;) { for(per = transfers; per;) {
bool retry; bool retry;
CURLcode result2 = post_per_transfer(global, per, result, &retry); long delay;
CURLcode result2 = post_per_transfer(global, per, result, &retry, &delay);
if(!result) if(!result)
/* don't overwrite the original error */ /* don't overwrite the original error */
result = result2; result = result2;

View File

@ -54,6 +54,9 @@ struct per_transfer {
char errorbuffer[CURL_ERROR_SIZE]; char errorbuffer[CURL_ERROR_SIZE];
bool added; /* set TRUE when added to the multi handle */ bool added; /* set TRUE when added to the multi handle */
time_t startat; /* when doing parallel transfers, this is a retry transfer
that has been set to sleep until this time before it
should get started (again) */
/* for parallel progress bar */ /* for parallel progress bar */
curl_off_t dltotal; curl_off_t dltotal;