Всем доброго дня!
Обнаружил, что течет память при завершении потоков:
Далаем вот такой простой тест:
>>>>>>>>
#include <stdio.h>
#include <pthread.h>
void *thread( void* in )
{
printf( "I'm running thread\n" );
return NULL;
}
int main( void )
{
pthread_t tid, tid2;
pthread_create( &tid, NULL, &thread, NULL );
pthread_create( &tid2, NULL, &thread, NULL );
/* wait until complete */
pthread_join( tid, NULL );
pthread_join( tid2, NULL );
return 0;
}
<<<<<<<<
собранный: gcc test.c -o test -lpthread
и запущеный через valgrind --tool=memcheck -v --leak-check=yes --show-reachable=yes --leak-resolution=high
показывает потерю 136 байт (68 на поток). По стеку видно, что
теряется TLS.
Кто-нибудь сталкивался с этим? Является ли это багом libc или я не
так завершаю поток?
libc: 2.3.6(fedora core 5), 2.3.5(ubuntu breezy)
P.S.
Если завершать через pthread_exit - потерей будет существенно больше :(.
>Кто-нибудь сталкивался с этим?
Насколько valgrind коворит это "баг" в libc, но т.к. судя по всему струтура
живет в течении жизни программы, и память ОС освобождает в конце,
это не совсем утечка.
у меня glibc-2.4:
supp: 15 dl_relocate_object
==16980== malloc/free: in use at exit: 272 bytes in 2 blocks.
==16980== malloc/free: 2 allocs, 0 frees, 272 bytes allocated.
==16980== 272 bytes in 2 blocks are possibly lost in loss record 1 of 1
==16980== at 0x4022BE7: calloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==16980== by 0x401135F: _dl_allocate_tls (in /lib/ld-2.4.so)
==16980== LEAK SUMMARY:
==16980== definitely lost: 0 bytes in 0 blocks.
==16980== possibly lost: 272 bytes in 2 blocks.
==16980== still reachable: 0 bytes in 0 blocks.
==16980== suppressed: 0 bytes in 0 blocks.
>Является ли это багом libc или я не
>так завершаю поток?
для линукс правильно, для *nix вообще надо установить состояние потока в joinable,
потому что оно не является соотоянием по умолчанию.
Если я правильно понимаю, то valgrind считает память после окончания
работы программы, таким образом статистика выдаваемая им - вполне
окончательная и структуры обязаны быть убраны.
Короче говоря - есть проблема. посмотрим в коде...
Странно, в каких это *nix у потока состояние PTHREAD_CREATE_DETACHED по-умолчанию?
По стандарту POSIX у атрибутов потока pthread_attr_t по умолчанию
опредено как раз состояние PTHREAD_CREATE_JOINABLE .
Мне просто интересно, чтобы не "нарваться".
P.S. Сколько ни работал с потоками (начиная с RedHat 7.1 и по RHEL4),
не встречал такой проблемы. Гонял тестовую прогу, создающую потоки и
печатающую из них ID потока часами - такого эффекта не наблюдал.
Может это взаимодействие с valgrind ?
Если нет, то сама пококовая библиотека вполне может организовать у себя кэширование (неподходящее слово, но лучше не придумывается) каких-нибудь структур данных, которое конечно же будет выглядеть как memory leak.
1. Есть у меня смутное ощущение что все потоки создаются JOINABLE, надо
POSIX вкуривать.
2. Да, NPTL используется.
Насчет кеширования - это не логично. Программа работающая долгое время
и создающая потоки, а потом уничтожающая в процессе работы не должна
терять память - иначе она сама себе вредит. Для меня проблема
серьезная, так как софт на котором я это отловил - создает потоки
тысячами в час - примерно 60 - 150k потерь в час, а так как это
демон - для системы могут наступить тяжелые времена в виде нехватки
памяти через месяц работы.
to RomanSA:
Да, в RHEL4 такой проблемы не наблюдается, зато в федоре 5 - 100%
воспроизводится.
IMHO: вообще удручает ситуация с утечками памяти в opensource.
как-то все не слишком гладко там, если брать демоны - то еще можно
жить, но если взять GUI - вешаться охота.
> Для меня проблема
> серьезная, так как софт на котором я это отловил - создает потоки
> тысячами в час - примерно 60 - 150k потерь в час
память то помечена не как "определенно потерянная", а как предположительно потерянная.
возможно намного облегчит жизнь создание пула потоков.
> вообще удручает ситуация с утечками памяти в opensource.
и чем она может удручать?
вы думаете в не opensource их нет?
Но в opensource ее возможно найти и исправить.
В данном случае valgrind даже сказал где,
если посмотреть в том модуле в glibc только пару раз вызывается calloc,
так что найти и исправить ошибку не является проблемой,
ну или запостите баг в багзилу.
"предположительно потерянная" - означает что до этой памяти программа
может достучаться и освободить ее, но этого по каким либо причинам
не делает.
> возможно намного облегчит жизнь создание пула потоков.
пул потоков есть, там все и теряется, из-за того, что периодически
количество потоков уменьшается для того что бы не занимать систему
бездействующими потоками.
> и чем она может удручать?
> вы думаете в не opensource их нет?
> Но в opensource ее возможно найти и исправить.
closesource вообще не рассматриваем - там и не такое можно словить :-)
У меня личные счеты с memory leak и я очень нервно к подобным ошибкам
отношусь. Потому и удручаюсь, ибо считаю что программа должна работать
хорошо и правильно :-). Работает хорошо, но вот что-бы правильно -
это не всегда(в смысле памяти), но это уже вопросы религии - что
первичней - функциональность или корректность.
> В данном случае valgrind даже сказал где,
> если посмотреть в том модуле в glibc только пару раз вызывается
> calloc,
> так что найти и исправить ошибку не является проблемой,
> ну или запостите баг в багзилу.
исправить можно, чем я сейчас и занимаюсь.
насчет багзиллы - я в самом начале попросил совета: баг это или
кривые ручки. Ответ пока неопределенный... :-(