]> granicus.if.org Git - curl/commitdiff
curl: make sure the parallel transfers do them all
authorDaniel Stenberg <daniel@haxx.se>
Tue, 10 Sep 2019 11:37:38 +0000 (13:37 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 10 Sep 2019 17:45:19 +0000 (19:45 +0200)
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

index 9b52258533c1a3e44a5a5f872a5e09c5b8c77c57..d2ad9642db4a119001ac9ba64c2ab3c05f445287 100644 (file)
@@ -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;
+      }
     }
   }