From: Daniel Stenberg Date: Tue, 30 Aug 2022 14:44:12 +0000 (+0200) Subject: tool_operate: reduce errorbuffer allocs X-Git-Tag: curl-7_86_0~311 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7be53774c41c59b47075fbaf758b1497f70b25d6;p=thirdparty%2Fcurl.git tool_operate: reduce errorbuffer allocs - 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 --- diff --git a/src/tool_operate.c b/src/tool_operate.c index 19e1c7b6b7..d9ea5a15bb 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -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; diff --git a/src/tool_operate.h b/src/tool_operate.h index a779239478..56e002a3f2 100644 --- a/src/tool_operate.h +++ b/src/tool_operate.h @@ -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[]); diff --git a/src/tool_writeout.c b/src/tool_writeout.c index 478e8cc46e..2789ee20bf 100644 --- a/src/tool_writeout.c +++ b/src/tool_writeout.c @@ -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;