From bbde0407d1e3750cfc161615491420217b718994 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Sep 2019 13:37:38 +0200 Subject: [PATCH] curl: make sure the parallel transfers do them all The logic could erroneously break the loop too early before all transfers had been transferred. Reported-by: Tom van der Woerdt Fixes #4316 Closes #4317 --- src/tool_operate.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/tool_operate.c b/src/tool_operate.c index 9b5225853..d2ad9642d 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1924,12 +1924,21 @@ static CURLcode create_transfers(struct GlobalConfig *global, static long all_added; /* number of easy handles currently added */ +/* + * add_parallel_transfers() sets 'morep' to TRUE if there are more transfers + * to add even after this call returns. sets 'addedp' to TRUE if one or more + * transfers were added. + */ static int add_parallel_transfers(struct GlobalConfig *global, - CURLM *multi) + CURLM *multi, + bool *morep, + bool *addedp) { struct per_transfer *per; CURLcode result; CURLMcode mcode; + *addedp = FALSE; + *morep = FALSE; for(per = transfers; per && (all_added < global->parallel_max); per = per->next) { if(per->added) @@ -1949,7 +1958,9 @@ static int add_parallel_transfers(struct GlobalConfig *global, return CURLE_OUT_OF_MEMORY; per->added = TRUE; all_added++; + *addedp = TRUE; } + *morep = per ? TRUE : FALSE; return CURLE_OK; } @@ -1962,16 +1973,19 @@ static CURLcode parallel_transfers(struct GlobalConfig *global, CURLcode result = CURLE_OK; int still_running = 1; struct timeval start = tvnow(); + bool more_transfers; + bool added_transfers; multi = curl_multi_init(); if(!multi) return CURLE_OUT_OF_MEMORY; - result = add_parallel_transfers(global, multi); + result = add_parallel_transfers(global, multi, + &more_transfers, &added_transfers); if(result) return result; - while(!done && !mcode && still_running) { + while(!done && !mcode && (still_running || more_transfers)) { mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL); if(!mcode) mcode = curl_multi_perform(multi, &still_running); @@ -2001,9 +2015,14 @@ static CURLcode parallel_transfers(struct GlobalConfig *global, (void)del_transfer(ended); } } while(msg); - if(removed) + if(removed) { /* one or more transfers completed, add more! */ - (void)add_parallel_transfers(global, multi); + (void)add_parallel_transfers(global, multi, &more_transfers, + &added_transfers); + if(added_transfers) + /* we added new ones, make sure the loop doesn't exit yet */ + still_running = 1; + } } }