]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_operate: reduce errorbuffer allocs
authorDaniel Stenberg <daniel@haxx.se>
Tue, 30 Aug 2022 14:44:12 +0000 (16:44 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 1 Sep 2022 07:25:00 +0000 (09:25 +0200)
- parallel transfers: only alloc and keep errorbuffers in memory for
  actual "live" transfers and not for the ones in the pending queue

- serial transfers: reuse the same fixed buffer for all transfers, not
  allocated at all.

Closes #9394

src/tool_operate.c
src/tool_operate.h
src/tool_writeout.c

index 19e1c7b6b7e6d4761770a42a8066a958733d2606..d9ea5a15bb2c06e300a88b3abf1eebb800014433 100644 (file)
@@ -347,6 +347,9 @@ static void AmigaSetComment(struct per_transfer *per,
 #define AmigaSetComment(x,y) Curl_nop_stmt
 #endif
 
+/* When doing serial transfers, we use a single fixed error area */
+static char global_errorbuffer[CURL_ERROR_SIZE];
+
 /*
  * Call this after a transfer has completed.
  */
@@ -378,9 +381,9 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
   else
 #endif
     if(!config->synthetic_error && result && global->showerror) {
+      const char *msg = per->errorbuffer;
       fprintf(global->errors, "curl: (%d) %s\n", result,
-              (per->errorbuffer[0]) ? per->errorbuffer :
-              curl_easy_strerror(result));
+              (msg && msg[0]) ? msg : curl_easy_strerror(result));
       if(result == CURLE_PEER_FAILED_VERIFICATION)
         fputs(CURL_CA_CERT_ERRORMSG, global->errors);
     }
@@ -656,6 +659,8 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
   free(per->this_url);
   free(per->outfile);
   free(per->uploadfile);
+  if(global->parallel)
+    free(per->errorbuffer);
 
   return result;
 }
@@ -706,7 +711,6 @@ static long url_proto(char *url)
 }
 
 /* create the next (singular) transfer */
-
 static CURLcode single_transfer(struct GlobalConfig *global,
                                 struct OperationConfig *config,
                                 CURLSH *share,
@@ -1364,7 +1368,10 @@ static CURLcode single_transfer(struct GlobalConfig *global,
           my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
         my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
         my_setopt_str(curl, CURLOPT_RANGE, config->range);
-        my_setopt(curl, CURLOPT_ERRORBUFFER, per->errorbuffer);
+        if(!global->parallel) {
+          per->errorbuffer = global_errorbuffer;
+          my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer);
+        }
         my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
 
         switch(config->httpreq) {
@@ -2196,6 +2203,7 @@ static CURLcode add_parallel_transfers(struct GlobalConfig *global,
   CURLcode result = CURLE_OK;
   CURLMcode mcode;
   bool sleeping = FALSE;
+  char *errorbuf;
   *addedp = FALSE;
   *morep = FALSE;
   if(all_pers < (global->parallel_max*2)) {
@@ -2219,6 +2227,13 @@ static CURLcode add_parallel_transfers(struct GlobalConfig *global,
     if(result)
       return result;
 
+    errorbuf = per->errorbuffer;
+    if(!errorbuf) {
+      errorbuf = malloc(CURL_ERROR_SIZE);
+      if(!errorbuf)
+        return CURLE_OUT_OF_MEMORY;
+    }
+
     /* parallel connect means that we don't set PIPEWAIT since pipewait
        will make libcurl prefer multiplexing */
     (void)curl_easy_setopt(per->curl, CURLOPT_PIPEWAIT,
@@ -2227,14 +2242,20 @@ static CURLcode add_parallel_transfers(struct GlobalConfig *global,
     (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb);
     (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFODATA, per);
     (void)curl_easy_setopt(per->curl, CURLOPT_NOPROGRESS, 0L);
+    (void)curl_easy_setopt(per->curl, CURLOPT_ERRORBUFFER, errorbuf);
 
     mcode = curl_multi_add_handle(multi, per->curl);
-    if(mcode)
+    if(mcode) {
+      free(errorbuf);
       return CURLE_OUT_OF_MEMORY;
+    }
 
     result = create_transfer(global, share, &getadded);
-    if(result)
+    if(result) {
+      free(errorbuf);
       return result;
+    }
+    per->errorbuffer = errorbuf;
     per->added = TRUE;
     all_added++;
     *addedp = TRUE;
index a779239478e730fd68cb1820b6fb9e4113a3eaa1..56e002a3f2bb4ba2872d643a8b8676e0715138be 100644 (file)
@@ -52,7 +52,6 @@ struct per_transfer {
   struct HdrCbData hdrcbdata;
   long num_headers;
   bool was_last_header_empty;
-  char errorbuffer[CURL_ERROR_SIZE];
 
   bool added; /* set TRUE when added to the multi handle */
   time_t startat; /* when doing parallel transfers, this is a retry transfer
@@ -72,6 +71,8 @@ struct per_transfer {
 
   /* NULL or malloced */
   char *uploadfile;
+  char *errorbuffer; /* alloced and assigned while this is used for a
+                        transfer */
 };
 
 CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[]);
index 478e8cc46e074e16c03b295ea9f7621d9d2b0be0..2789ee20bf44a451386b03dc3a26d454d01499cb 100644 (file)
@@ -195,8 +195,8 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar,
     switch(wovar->id) {
     case VAR_ERRORMSG:
       if(per_result) {
-        strinfo = per->errorbuffer[0] ? per->errorbuffer :
-                  curl_easy_strerror(per_result);
+        strinfo = (per->errorbuffer && per->errorbuffer[0]) ?
+          per->errorbuffer : curl_easy_strerror(per_result);
         valid = true;
       }
       break;