Return Value pthread_exit() does not return.
Also, in main() , return will implicitly call exit() , and thus terminate the program, whereas pthread_exit() will merely terminate the thread, and the program will remain running until all threads have terminated or some thread calls exit() , abort() or another function that terminates the program.
You are not required to call pthread_exit . The thread function can simply return when it's finished.
The pthread_exit() function terminates the calling thread and makes the value value_ptr available to any successful join with the terminating thread. Any cancellation cleanup handlers that have been pushed and not yet popped are popped in the reverse order that they were pushed and then executed.
The following minimal test case exhibits the behaviour you describe:
#include <pthread.h>
#include <unistd.h>
void *app1(void *x)
{
sleep(1);
pthread_exit(0);
}
int main()
{
pthread_t t1;
pthread_create(&t1, NULL, app1, NULL);
pthread_join(t1, NULL);
return 0;
}
valgrind --leak-check=full --show-reachable=yes
shows 5 blocks allocated from functions called by pthread_exit()
that is unfreed but still reachable at process exit. If the pthread_exit(0);
is replaced by return 0;
, the 5 blocks are not allocated.
However, if you test creating and joining large numbers of threads, you will find that the amount of unfreed memory in use at exit does not increase. This, and the fact that it is still reachable, indicates that you're just seeing an oddity of the glibc implementation. Several glibc functions allocate memory with malloc()
the first time they're called, which they keep allocated for the remainder of the process lifetime. glibc doesn't bother to free this memory at process exit, since it knows that the process is being torn down anyway - it'd just be a waste of CPU cycles.
Not sure if you're still interested in this, but I am currently debugging a similar situation. Threads that use pthread_exit
cause valgrind to report reachable blocks. The reason seems to be fairly well explained here:
https://bugzilla.redhat.com/show_bug.cgi?id=483821
Essentially it seems pthread_exit
causes a dlopen
which is never cleaned up explicitly when the process exits.
Are you actually using C++, by any chance? To clarify - your source file ends with a .c
extension, and you are compiling it with gcc
, not g++
?
It seems reasonably likely that your function is allocating resources that you expect to be cleaned up automatically when the function returns. Local C++ objects like std::vector
or std::string
do this, and their destructors probably won't be run if you call pthread_exit
, but would be cleaned up if you just return.
My preference is to avoid low-level APIs such as pthread_exit
, and always just return from the thread function, where possible. They're equivalent, except that pthread_exit
is a de-facto flow-control construct that bypasses the language you're using, but return
doesn't.
It looks like calling exit() (and, apparently, pthread_exit()) leaves automatically-allocated variables allocated. You must either return or throw in order to properly unwind.
Per C++ valgrind possible leaks on STL string:
@Klaim: I don't see where that document says that I am wrong, but if it does then it is wrong. To quote the C++ standard (§18.3/8): "Automatic objects are not destroyed as a result of calling exit()." – James McNellis Sep 10 '10 at 19:11
Since doing a "return 0" instead of "pthread_exit(0)" seemed to solve your problem (and mine.. thanks), I'm assuming that the behavior is similar between the two.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With