Context
System: Fedora 40
Library Used: pthread.h
Details: Read "To the point" if not interested
I apologize for providing no code here as the whole program is more than 4000 lines of code and is not hosted on Github either. I will try my best to explain in words.
The program is a simple database. It is for my parent's shop. The computer running Linux has the program constantly running. I use files per customer to store everything about them. There are salesmen as well and so the program has to be able to open and ready files for many salesmen and customers at once.
The overall structure of the program is simple: A manager thread runs and it starts new thread per customer or salesmen. So far 6 threads were the max that it hit but with more salesmen, I think having one process entirely for salesmen was a better choice. The context switching hampers the program's speed and so when a file for a salesmen needed to be opened, the manager thread would create a new process.
To the point
Each thread maps 4KB of memory as ANONYMOUS and PRIVATE and has a memory manager for it. This mapped memory serves as cache for any previous extensive computation. Each thread has its own MUTEXES and CONDITION VARIABLES. There is also a request queue and a request handler managed by the Managing thread. The handler also has its own lock and condition variable.
What I found: I researched on multi-processing programs. I found out that it was better to re-initialize everything after forking so I used the Manager thread to do the fork. That way the Manager thread got replicated. But I also found that the mapped memory, locks and condition variables, malloced memory, basically everything also got inherited. The locks and condition variables of threads not running also got inherited but they weren't running so I freed all allocated memory, destroyed locks and unmapped the memory except when it came to condition variables, everytime, the third thread's condition variable could not be freed. For some reason, the pthread_cond_destroy function doesn't return at all.
LLM's Suggestion
I presented the problem to ChatGPT and Gemini and the solution I got: Don't attempt to free the inherited locks and condition variables or even the memory, just re-initialize everything. I couldn't bring myself to leave unused memory allocated.
forkis duplicated. If some locks were held by other threads at the moment of fork, those will remain forever stuck in the child process. The main use of fork is to call exec afterwards. Combining threads and forking is asking for pain.forkin a multithreaded program and find yourself in the child process, only the library functions listed here are safe to call (everything else may be using internal locks that may be unavailable to you). Noprintf, nomalloc/free, nopthread_cond_*.