Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pthread_create() and memory leaks

This question seems to be asked a lot. I had some legacy production code that was seemingly fine, until it started getting many more connections per day. Each connection kicked off a new thread. Eventually, it would exhaust memory and crash.

I'm going back over pthread (and C sockets) which I've not dealt with in years. The tutorial I had was informative, but I'm seeing the same thing when I use top. All the threads exit, but there's still some virtual memory taken up. Valgrind tells me there is a possible memory loss when calling pthread_create(). The very basic sample code is below.

The scariest part is that pthread_exit( NULL ) seems to leave about 100m in VIRT unaccounted for when all the threads exit. If I comment out this line, it's much more liveable, but there is still some there. On my system it start with about 14k, and ends with 47k.

If I up the thread count to 10,000, VIRT goes up to 70+ gigs, but finishes somewhere around 50k, assuming I comment out pthread_exit( NULL ). If I use pthread_exit( NULL ) it finishes with about 113m still in VIRT. Are these acceptable? Is top not telling me everything?

void* run_thread( void* id )
{
    int thread_id = *(int*)id;
    int count = 0;
    while ( count < 10 ) {
        sleep( 1 );
        printf( "Thread %d at count %d\n", thread_id, count++ );
    }

    pthread_exit( NULL );
    return 0;
}

int main( int argc, char* argv[] )
{
    sleep( 5 ); 
    int thread_count    = 0;
    while( thread_count < 10 ) {
        pthread_t my_thread;
        if ( pthread_create( &my_thread, NULL, run_thread, (void*)&thread_count ) < 0 )   {
            perror( "Error making thread...\n" );
            return 1;
        }

        pthread_detach( my_thread );
        thread_count++;
        sleep( 1 );
    }

    pthread_exit( 0 );  // added as per request
    return 0;
}
like image 686
kiss-o-matic Avatar asked Aug 05 '14 02:08

kiss-o-matic


People also ask

What happens on pthread_create?

The pthread_create() function shall create a new thread, with attributes specified by attr, within a process. If attr is NULL, the default attributes shall be used. If the attributes specified by attr are modified later, the thread's attributes shall not be affected.

What happens when a Pthread exits?

Exiting the initial thread (for example by calling the pthread_exit subroutine from the main routine) does not terminate the process. It only terminates the initial thread. If the initial thread is terminated, the process will be terminated when the last thread in it terminates.

What is possibly lost in Valgrind?

possibly lost: heap-allocated memory that was never freed to which valgrind cannot be sure whether there is a pointer or not. still reachable: heap-allocated memory that was never freed to which the program still has a pointer at exit.

Do I need pthread_join?

Yes if thread is attachable then pthread_join is must otherwise it creates a Zombie thread. Agree with answers above, just sharing a note from man page of pthread_join. After a successful call to pthread_join(), the caller is guaranteed that the target thread has terminated.


1 Answers

I know this is rather old question, but I hope others wil benefit. This is indeed a memory leak. The thread is created with default attributes. By default the thread is joinable. A joinable threads keeps its underlying bookkeeping until it is finished... and joined. If a thread is never joined, set de Detached attribute. All (thread) resources will be freed once the thread terminates. Here's an example:

pthread_attr_t attr;
pthread_t thread;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, 1);
pthread_create(&thread, &attr, &threadfunction, NULL);
pthread_attr_destroy(&attr);
like image 82
Lammy Avatar answered Oct 13 '22 00:10

Lammy