Multithreaded Fork

Multithreaded fork

After a fork, only one thread is running in the child. This is a POSIX standard requirement. See the top answer to the question fork and existing threads ?.

Calling fork on a multithreaded process

Read carefully what POSIX says about fork() and threads. In particular:

  • 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.

The child process will have a single thread running in the context of the calling thread. Other parts of the original process may be tied up by threads that no longer exist (so mutexes may be locked, for example).

The rationale section (further down the linked page) says:

There are two reasons why POSIX programmers call fork(). One reason is to create a new thread of control within the same program (which was originally only possible in POSIX by creating a new process); the other is to create a new process running a different program. In the latter case, the call to fork() is soon followed by a call to one of the exec functions.

The general problem with making fork() work in a multi-threaded world is what to do with all of the threads. There are two alternatives. One is to copy all of the threads into the new process. This causes the programmer or implementation to deal with threads that are suspended on system calls or that might be about to execute system calls that should not be executed in the new process. The other alternative is to copy only the thread that calls fork(). This creates the difficulty that the state of process-local resources is usually held in process memory. If a thread that is not calling fork() holds a resource, that resource is never released in the child process because the thread whose job it is to release the resource does not exist in the child process.

When a programmer is writing a multi-threaded program, the first described use of fork(), creating new threads in the same program, is provided by the pthread_create() function. The fork() function is thus used only to run new programs, and the effects of calling functions that require certain resources between the call to fork() and the call to an exec function are undefined.

Multi-threaded fork()

This is a thorny question.

POSIX has pthread_atfork() to work through the mess of mixing forks and thread creation. The NOTES section of that man page discusses mutexes etc. However, it acknowledges that getting it right is hard.

The function isn't so much an alternative to fork() as it is a way to explain to the pthread library how your program needs to be prepared for the use of fork().

In general not trying to launch a thread from the child of fork but either exiting that child or calling exec asap, will minimize problems.

This post has a good discussion of pthread_atfork().

How to safely fork() a multi-threaded process?


So now what I want to do is to fork the process before the 3rd party static library is loaded. So is there a proper way to achieve this?

"Before the static library is loaded" is not a thing, static libraries are linked in at build time, not loaded dynamically at runtime.

The library will start a thread triggered by the initialization of a global variable

You should consider using a better-designed library, or work with the maintainer to come up with a better-thought-out initialization scheme. Life before main is usually a bad idea. Spawning threads before main is a really bad idea. Alternatives might be, use a lazy static that gets triggered whenever an API of the library is called, or better yet, introducing an explicit init function, or using context pointers so that the user can manage library state. Sorry, it sounds like this thing is a tire fire and theres no sane way to fork it until you invest some time in fixing it.

Is fork process an example of Multi threading in C?

No, it isn't. C doesn't even know fork(), but I assume you're talking about the POSIX function fork(). This creates a new process, which runs completely isolated (with a few exceptions like it can inherit open file descriptors) from the parent process.

For threading in C, have a look at the thread functions in C11. Unfortunately, the support for these isn't very widespread, but there's also the POSIX threading interface pthreads.

C++ fork(), multi-threading and OS's concepts

From the fork() documentation:

RETURN VALUE

Upon successful completion, fork() shall return 0 to the child process
and shall return the process ID of the child process to the parent process.

Your code assumes any zero return value is an error.

Continuing:

Both processes shall continue to execute from the fork() function.
Otherwise, -1 shall be returned to the parent process, no child
process shall be created, and errno shall be set to indicate the
error.

A -1 return value is an error indication.

Simple multi-threaded Java app - ExecutorService? Fork/Join? Spliterators?


Parallel stream

Use none of these. Parallel streams are going to be enough to deal with this problem much more straightforwardly than any of the alternatives you list.

return Arrays.parallelStream(inputArray)
.filter(n -> checkIfNumberIsPrime(n))
.boxed()
.collect(Collectors.toSet());

For more info, see The Java™ Tutorials > Aggregate Operations > Parallelism.

Synchronisation in fork()ed multithreaded process

The new process has just one running thread initially. That process' copy of the mutex is forever locked, unless explicitly reinitialized or unless the mutex was shared across processes (attribute PTHREAD_PROCESS_SHARED, not everywhere supported).

Here's what the spec has to about this situation say in its discussion of pthread_atfork(), which function was introduced in part to address this unpleasantness:

Consider the case where one thread has a mutex locked and the state
covered by that mutex is inconsistent while another thread calls
fork(). In the child, the mutex is in the locked state (locked by a
nonexistent thread and thus can never be unlocked). Having the child simply reinitialize the mutex is unsatisfactory since this approach does not resolve the question about how to correct or otherwise deal with the inconsistent state in the child.



Related Topics



Leave a reply



Submit