LINUX.ORG.RU

В libcurl утечка памяти чтоли

 , ,


0

3

Сделал пачку потоков в которых забирал файлы по https
Заметил что сильно отъедает память Для проверки сделал тестовый кусок кода, поднял апач и в цикле забирал один и тот же файл:

#include <curl/curl.h>
#include <thread>

size_t writefunc(void* ptr, size_t size, size_t nmemb, std::string* userdata) {

    return size*nmemb;
}

void thread_test() {

    const char* url = "https://КАКОЙ-ТО УРЛ";

    CURL* curl;
    CURLcode res;

    while(true) {

    curl = curl_easy_init();

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); // Не будем проверять сертификаты
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); // Не будем проверять сертификаты

    //чтобы не валило в stdout
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
//	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_data);


//	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    res = curl_easy_perform(curl);

    //Если что-то пошло не так...
    if(res != CURLE_OK) {

        curl_easy_strerror(res);
    } else {

    //Все OK

    }

    curl_easy_cleanup(curl);

    }


}

main() {

    curl_global_init(CURL_GLOBAL_ALL);

    int thread_num = 100;

    //Запускаем потоки
    std::thread threads[thread_num];
    for(int i = 0 ; i < thread_num ; i++) {

    threads[i] = std::thread(thread_test);
    }

    for(int i = 0 ; i < thread_num ; i++) {

    threads[i].join();
    }

}


собираем
g++ -std=c++11 curl-test-0.cpp -lcurl -lpthread -o curl-test-0
ldd:
	linux-vdso.so.1 (0x00007ffcf8d6c000)
	libcurl-nss.so.4 => /usr/lib/x86_64-linux-gnu/libcurl-nss.so.4 (0x00007f679df56000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f679dd39000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f679d9b7000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f679d6b3000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f679d49c000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f679d0fd000)
	libnghttp2.so.14 => /usr/lib/x86_64-linux-gnu/libnghttp2.so.14 (0x00007f679ced7000)
	libidn2.so.0 => /usr/lib/x86_64-linux-gnu/libidn2.so.0 (0x00007f679ccb5000)
	librtmp.so.1 => /usr/lib/x86_64-linux-gnu/librtmp.so.1 (0x00007f679ca98000)
	libssh2.so.1 => /usr/lib/x86_64-linux-gnu/libssh2.so.1 (0x00007f679c86c000)
	libpsl.so.5 => /usr/lib/x86_64-linux-gnu/libpsl.so.5 (0x00007f679c65e000)
	libnss3.so => /usr/lib/x86_64-linux-gnu/libnss3.so (0x00007f679c314000)
	libnssutil3.so => /usr/lib/x86_64-linux-gnu/libnssutil3.so (0x00007f679c0e6000)
	libsmime3.so => /usr/lib/x86_64-linux-gnu/libsmime3.so (0x00007f679beb9000)
	libssl3.so => /usr/lib/x86_64-linux-gnu/libssl3.so (0x00007f679bc61000)
	libplds4.so => /usr/lib/x86_64-linux-gnu/libplds4.so (0x00007f679ba5d000)
	libplc4.so => /usr/lib/x86_64-linux-gnu/libplc4.so (0x00007f679b858000)
	libnspr4.so => /usr/lib/x86_64-linux-gnu/libnspr4.so (0x00007f679b618000)
	libgssapi_krb5.so.2 => /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f679b3cd000)
	libkrb5.so.3 => /usr/lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f679b0f3000)
	libk5crypto.so.3 => /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f679aec0000)
	libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f679acbc000)
	liblber-2.4.so.2 => /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007f679aaad000)
	libldap_r-2.4.so.2 => /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007f679a85c000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f679a642000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f679e3dc000)
	libunistring.so.0 => /usr/lib/x86_64-linux-gnu/libunistring.so.0 (0x00007f679a32b000)
	libgnutls.so.30 => /usr/lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007f6799f92000)
	libhogweed.so.4 => /usr/lib/x86_64-linux-gnu/libhogweed.so.4 (0x00007f6799d5d000)
	libnettle.so.6 => /usr/lib/x86_64-linux-gnu/libnettle.so.6 (0x00007f6799b26000)
	libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f67998a3000)
	libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f6799593000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f679938f000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f6799187000)
	libkrb5support.so.0 => /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f6798f7b000)
	libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f6798d77000)
	libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f6798b60000)
	libsasl2.so.2 => /usr/lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007f6798945000)
	libp11-kit.so.0 => /usr/lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f67986e0000)
	libidn.so.11 => /lib/x86_64-linux-gnu/libidn.so.11 (0x00007f67984ac000)
	libtasn1.so.6 => /usr/lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007f6798299000)
	libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f6798085000)
	libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f6797e7c000)

Вскоре после запуска наблюдаем увеличение отъедаемой памяти. На гитхабе были какие-то разговоры про подобное, но решение не засветили. Специально использовал NSS потомучто на офсайте curl сказано что он потокобезопасный, а OpenSSL не всех версий. Проблема наблюдается только при работе по HTTPS.
Это на стретче 64х,

curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2q zlib/1.2.8 libidn2/0.16 libpsl/0.17.0 (+libidn2/0.16) libssh2/1.7.0 nghttp2/1.18.1 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL

Как быть?



Последнее исправление: ocr (всего исправлений: 2)

Специально использовал NSS потомучто на офсайте curl сказано что он потокобезопасный, а OpenSSL не всех версий.

А как именно ты «использовал NSS»? У тебя же сам curl говорит, что он собран с OpenSSL 1.0.2q.

Deleted
()

А почему бы для этой задачи не взять го?

nikolnik ★★★
()
Ответ на: комментарий от Deleted

это собрана утилита curl которая ставится из репы

ocr
() автор топика

то же самое происходит на джесси 32х

ocr
() автор топика

если перед каждым запросом делать curl_global_init, а после запроса curl_global_cleanup, то отжирания памяти не наблюдается

ocr
() автор топика
Ответ на: комментарий от ocr

если перед каждым запросом делать curl_global_init, а после запроса curl_global_cleanup, то отжирания памяти не наблюдается

Эти функции точно не являются потокобезопасными.

Deleted
()
Ответ на: комментарий от Deleted

я знаю что не потокобезопасные. запросы делал в цикле в одном потоке.
все это касается только HTTPS
Как решить вопрос непонятно.

ocr
() автор топика
Ответ на: комментарий от Deleted

Мне кажется он чёт некорректно использует. У меня с openssl нормально работало, кода там побольше было правда. А в примерах на сайте есть и для gnutls.

anonymous
()
Ответ на: комментарий от ocr

мне вот интересно как вы в дальнейшем собираетесь работать в той компании в которую вас собеседуют или наняли, если в трех строчках разобраться не в силах ?

anonymous
()
Ответ на: комментарий от anonymous

я не знал что придется пилить всякие костыли и в таких дебрях копаться. скажут досвидания, «отнесусь с пониманием», я знаю что как спец сейчас я гавно. Хотябы буду знать что приложил все усилия что мог

ocr
() автор топика
Ответ на: комментарий от anonymous

уже увидел и делаю это
интересная ситуация со стретчем и dev-пакетами для curl: есть libcurl4-openssl-dev, но он для openssl 1.0.2, а тот что тред-сэйф версии 1.1 для него нет dev-пакета для curl и придется либо собирать с ним curl руками и делать LD_PRELOAD, либо делать блокировки как по ссылке

ocr
() автор топика

Похоже, буду оригинален, и скажу следующее:

valgrind даёт много false positives, особенно в приложения использующих кондиционные переменные.

Вместо этого можно попробовать штатные механизмы компилятора(curl придётся собрать из исходников и может ещё что-то):

man gcc | grep asan -C 10

Можно ещё подумать как-то так. Хотя я бы попробовал сначала руками собрать.

pon4ik ★★★★★
()
Ответ на: комментарий от anonymous

спасибо, анон
для OpenSSL версий старше 1.1 понапилил блокировок как в примере и все перестало течь

Только с NSS непонятно почему протекает, на офсайте сказано что тредсейф

ocr
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.