I wondered how to terminate a thread correctly without creating any memory leaks.
I have created a more straightforward program that demonstrates my issue. In the following code, I have a parent thread made in main, and the parent threads creates six threads, but for this example, I have just completed one to keep it simple. The parent thread will ask for the user input, which, if it is EXIT, will need to terminate all children threads. Otherwise, if it is anything else, it will continue processing and join at the very end. The thread for this example prints out a string and then returns.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void *ParentThread(void * args);
void *oneThread(void *args);
void *twoThread(void *args);
int main(int argc, char const *argv[])
{
/* Declare parent thread */
pthread_t parent;
/* Create parent thread */
pthread_create(&parent, NULL, ParentThread, NULL);
pthread_join(parent, NULL);
return 0;
}
void *ParentThread(void * args)
{
char sUserInput[10];
pthread_t A;
pthread_create(&A, NULL, oneThread, NULL);
scanf("s", sUserInput);
/* Check if input is 'EXIT' */
if(strcmp(sUserInput, "EXIT") == 0)
{
/* Terminate Threads */
pthread_cancel(A);
}
else
{
/*
Other actions are performed
*/
pthread_join(A, NULL);
}
return NULL;
}
void *oneThread(void *args)
{
/* just an example to see if the thread is working */
printf("thread one\n");
return NULL;
}
When running the program, it will print out "thread one" and then ask for input for the user. If the user puts in EXIT, it will terminate the threads, while anything else will join the threads. When running Valgrind, I get the following results:
Input - EXIT
HEAP SUMMARY:
==217== in use at exit: 272 bytes in 1 blocks
==217== total heap usage: 4 allocs, 3 frees, 8,736 bytes allocated
==217==
==217== LEAK SUMMARY:
==217== definitely lost: 0 bytes in 0 blocks
==217== indirectly lost: 0 bytes in 0 blocks
==217== possibly lost: 272 bytes in 1 blocks
==217== still reachable: 0 bytes in 0 blocks
==217== suppressed: 0 bytes in 0 blocks
enter code here
Input - Test
==220== HEAP SUMMARY:
==220== in use at exit: 0 bytes in 0 blocks
==220== total heap usage: 4 allocs, 4 frees, 8,736 bytes allocated
==220==
==220== All heap blocks were freed -- no leaks are possible
Please let me know if you need any more information or clarification
CodePudding user response:
The thread cancellation doesn't release its resources:
From man pthread_create
A thread may either be joinable or detached. If a thread is joinable, then another thread can call pthread_join(3) to wait for the thread to terminate and fetch its exit status. Only when a terminated joinable thread has been joined are the last of its resources released back to the system. When a detached thread terminates, its resources are automatically released back to the system: it is not possible to join with the thread in order to obtain its exit status.
So, just call pthread_join
or you cancelled thread to get its resource back and make valgrind happy.
The other solution is to detach it.
Either pthread_join(3) or pthread_detach() should be called for each thread that an application creates, so that system resources for the thread can be released. (But note that the resources of any threads for which one of these actions has not been done will be freed when the process terminates.)
CodePudding user response:
Even if you cancel a thread, you still need to join it in order to release all resources associated with it.
After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status. (Joining with a thread is the only way to know that cancellation has completed.)
First, there would be absolutely no way to implement this provision if pthread_cancel
just completely erased all traces of the thread from the system. Second, pthread_cancel
may or may not cancel a thread immediately. It sends a cancellation request. It is up to the thread to honour it or not, or when to honour it. You just cannot assume the thread was cancelled immediately after pthread_cancel
returns. A running thread naturally consumes some resources. If you exit
after pthread_cancel
but before the thread is actually cancelled, valgring
will happily report lost memory.