falhumai falhumai - 3 months ago 32
C Question

Getting Leaks Even After pthread_detach

I am trying to make self-cleanup thread code to release pthread_t resources if I terminate the whole program from a side thread using pthread_detach, but I am still getting memory leaks reports from valgrind with possibly lost bytes. Here is my sample code snippet:

pthread_t main_thread;
pthread_t second_thread;

void* thread_func() {
pthread_detach(pthread_self());
exit(0);
}

int main() {
main_thread = pthread_self(); // record main thread in case needed later
pthread_create(&second_thread, NULL, thread_func, NULL);
while(1); // making main thread wait using a busy-wait (in case pthread_join) interferes
// with pthread_detach (that's another question though: does pthread_join called
// from another thread overlaps with pthread_detach from the same thread?)


}





Can anyone please help me indicate where I forgot to release any allocated resources?

Answer

So, I just found an amazing solution to the problem I came up with days ago, and I would like to share it.

Just a reminder about what is the original problem is: the problem is how to cleanup thread leaks after calling a full process exit (this will not be an actual leak in production code, but this is just to make valgrind, for example, happy!!).

So the solution I came up with is:

Make the main thread just like any other thread, by creating a thread for just the "main" thread (I know, this is will increase memory usage, and it won't be very efficient). The actual main thread will then be constantly checking for any exit signal sent from any thread, and if so, cleanup all threads and just exit. Other threads will send an exit signal when needed, and will wait for the actual main thread to clean them up (including the mockup "main" thread that contains the intended main thread code).

Here is a pseudocode to exemplify what I mentioned above:

threadId1;
threadId2;
mainThreadId;
willExit = false;
exitStatusCode;
mainThreadArgs;

exit_cleanup(exitStatusCodeArg) {
    exitStatusCode = exitStatusArg;
    willExit = true;
    while(true);
}

threadFunc1() {
    // Example thread code 1
    exit_cleanup(0);
}

threadFunc2() {
    // Example thread code 2
    if (/*some error*/)
        exit_cleanup(-1);
}

mainThreadFunc() {
    // some code (could be long, and may create side threads here)

    // by default, main thread should call exit_cleanup(0) at the end, as
    // exiting the main thread should also cancel all running threads
    exit_cleanup(0);
}

cleanUp() {
    while (willExit != false);
    for (all thread saved globally) {
        cancel and join current thread;
    }
    exit(exitStatusCode);
}

main(args) {
    mainThreadArgs = args;
    create_thread(mainThreadId, mainThreadFunc);
    cleanUp();
}



From the above code, I don't see any reason why valgrind, or any other memory leak checker, would complain for any "still reachable" or "possibly lost" leaks.

Any corrections on my solution are appreciated!!