There are two ways for programs to achieve concurrency on Unix-like systems:
fork(2) and POSIX threads. Programmers tend to use one or the
other when writing their programs, but what happens if you try to combine them?
One of the more obscure semantic about
fork(2) is described in the POSIX
A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
In other words, if thread A acquires a lock and thread B calls
fork(2), then thread B in the child process may never acquire the lock.
POSIX provides a
pthread_atfork(3) function to
assist in handling the state of the parent and child processes before and after
fork(2). What makes mixing these concurrency patterns challenging is
not being certain about the state of library functions after forking a process.
For example, to be POSIX-compliant, functions like
must be thread-safe, this implies the implementation has a lock burried
somewhere within the implementation. Additionally, the state of the lock after
fork(2) is dubious. If a function has any chance of being fork-safe
then it will need to check the return value of
pthread_mutex_lock(3) and re-initialize the lock
when the function returns
This work is licensed under a Creative Commons License.