Random memory leak is detected when calling curl_multi_cleanup before the associated easy handles are closed.
Steps to reproduce.
Build the following sample multi_app application:
#include <stdio.h>
#include <string.h>
/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>
/* curl stuff */
#include <curl/curl.h>
#define HANDLECOUNT 2 /* Number of simultaneous transfers */
/* The maximum number of curl_multi_perform iterations to perform before
* calling curl_multi_cleanup.
*/
#define MAX_ITERATIONS 14
int main(void)
{
CURL *handles[HANDLECOUNT];
CURLM *multi_handle;
int still_running = 1; /* keep number of running handles */
int i;
int iteration = 0;
CURLMsg *msg; /* for picking up messages with the transfer status */
int msgs_left; /* how many messages are left */
/* Allocate one CURL handle per transfer */
for (i = 0; i < HANDLECOUNT; i++) {
handles[i] = curl_easy_init();
curl_easy_setopt(handles[i], CURLOPT_URL, "https://example.com");
}
/* init a multi stack */
multi_handle = curl_multi_init();
/* add the individual transfers */
for(i = 0; i < HANDLECOUNT; i++)
curl_multi_add_handle(multi_handle, handles[i]);
while (still_running) {
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
if (iteration++ >= MAX_ITERATIONS)
goto out;
if (still_running)
/* wait for activity, timeout or "nothing" */
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
if (mc)
break;
}
/* Free the CURL handles */
for(i = 0; i < HANDLECOUNT; i++) {
curl_multi_remove_handle(multi_handle, handles[i]);
curl_easy_cleanup(handles[i]);
}
curl_multi_cleanup(multi_handle);
return 0;
}
Run the application with valgrind using the following shell script:
#!/bin/sh
while valgrind -q --error-exitcode=1 --leak-check=full ./multi_app > /dev/null; do
echo "Retrying..."
done
Depending on your computer's speed the leak will appear after a few tries:
Retrying...
==146245== 20,162 (1,280 direct, 18,882 indirect) bytes in 2 blocks are definitely lost in loss record 81 of 81
==146245== at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==146245== by 0x495877A: ssl_session_dup (ssl_sess.c:110)
==146245== by 0x496ABD3: tls_process_new_session_ticket (statem_clnt.c:2620)
==146245== by 0x4965D8C: read_state_machine (statem.c:636)
==146245== by 0x4965D8C: state_machine.part.0 (statem.c:434)
==146245== by 0x493C729: ssl3_read_bytes (rec_layer_s3.c:1658)
==146245== by 0x4943765: ssl3_read_internal (s3_lib.c:4465)
==146245== by 0x494EE17: SSL_read (ssl_lib.c:1783)
==146245== by 0x48E5D5B: ossl_closeone.isra.0 (openssl.c:1407)
==146245== by 0x48E5DE5: ossl_close (openssl.c:1427)
==146245== by 0x48ED11E: Curl_ssl_close (vtls.c:676)
==146245== by 0x48DA583: conn_shutdown (url.c:752)
==146245== by 0x48DA583: Curl_disconnect (url.c:870)
==146245== by 0x4889D92: Curl_conncache_close_all_connections (conncache.c:555)
Environment
curl 7.78
openSSL 1.1.1.k and openSSL 1.1.1.l
Notes
The memory leak appeared starting from curl 7.78 with the following commit
b249592d29ae0a2b3e8e07fdbc01f33b5a5b8420.
For know I have managed to reproduce it only with openSSL backend and not with
mbedTLS.
To reproduce the issue there needs to be at least two simultaneous connections
and the cleanup operations need to be close in time to exit.
Random memory leak is detected when calling
curl_multi_cleanupbefore the associated easy handles are closed.Steps to reproduce.
Build the following sample multi_app application:
Run the application with
valgrindusing the following shell script:Depending on your computer's speed the leak will appear after a few tries:
Environment
curl 7.78openSSL 1.1.1.kandopenSSL 1.1.1.lNotes
The memory leak appeared starting from
curl 7.78with the following commitb249592d29ae0a2b3e8e07fdbc01f33b5a5b8420.
For know I have managed to reproduce it only with
openSSLbackend and not withmbedTLS.To reproduce the issue there needs to be at least two simultaneous connections
and the cleanup operations need to be close in time to exit.