From 757dfdfb55a9dea43041b4ab4f1373d34c16dded Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 26 Feb 2024 09:50:49 +0100 Subject: [PATCH] multi: make add_handle free any multi_easy If the easy handle that is being added to a multi handle has previously been used for curl_easy_perform(), there is a private multi handle here that we can kill off. While it flushes some caches etc for the easy handle would it be used for an easy interface transfer again after being used in the multi stack, this cleanup simplifies behavior and uses less memory. Closes #12992 --- lib/easy.c | 6 ++++-- lib/multi.c | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/easy.c b/lib/easy.c index 7ea1ce1f63..e6bda9bc8b 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -742,7 +742,6 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) multi = Curl_multi_handle(1, 3, 7); if(!multi) return CURLE_OUT_OF_MEMORY; - data->multi_easy = multi; } if(multi->in_callback) @@ -751,15 +750,18 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) /* Copy the MAXCONNECTS option to the multi handle */ curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects); + data->multi_easy = NULL; /* pretend it does not exist */ mcode = curl_multi_add_handle(multi, data); if(mcode) { curl_multi_cleanup(multi); - data->multi_easy = NULL; if(mcode == CURLM_OUT_OF_MEMORY) return CURLE_OUT_OF_MEMORY; return CURLE_FAILED_INIT; } + /* assign this after curl_multi_add_handle() */ + data->multi_easy = multi; + sigpipe_ignore(data, &pipe_st); /* run the transfer */ diff --git a/lib/multi.c b/lib/multi.c index c6869a3155..e0e871fe67 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -530,6 +530,13 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, multi->dead = FALSE; } + if(data->multi_easy) { + /* if this easy handle was previously used for curl_easy_perform(), there + is a private multi handle here that we can kill */ + curl_multi_cleanup(data->multi_easy); + data->multi_easy = NULL; + } + /* Initialize timeout list for this handle */ Curl_llist_init(&data->state.timeoutlist, NULL);