Spawn process from multithreaded application?

Calling fork should be safe if you limit yourself to "raw" system calls ( syscall(SYS_fork) syscalll(SYS_execve, ...) etc.). Call into any glibc routine, and you'll be in a lot of trouble.

Up vote 4 down vote favorite 1 share g+ share fb share tw.

I have a situation where I need to spawn a helper process from within a very large, multithreaded application, which I do not have complete control over. Right now I'm using fork()/exec(). This works a lot of the time, but in some circumstances the child crashes weirdly before the exec() happens.

I'm suspecting this is because fork()ing multithreaded applications is generally considered to be a Really Bad Idea. I would really, really like a way to start a process atomically, without fork()ing the parent: with all file descriptors closed, environment set up the way I want, CWD set, etc. This should avoid all the horror of fork()ing my multithreaded parent app, and dealing with file descriptor inheritance, etc. posix_spawn() should be ideal. Unfortunately, on Linux, posix_spawn() is implemented using fork() and exec()... vfork() is defined to suspend the parent process until the child calls exec().

This would appear to be more like what I want, but my understanding was that vfork() is generally considered a historical relic these days and is equivalent to fork() --- is this still the case? What's the least bad way of dealing with this? Note that: I cannot spawn my process before any threads start (because I can't run code at that point) I cannot redesign my application not to need the helper process, due to external requirements I cannot suspend all my threads before spawning the helper process, because they don't belong to me This is on Linux.

Java is involved, but all my code is in C. C linux unix process fork link|improve this question edited Nov 16 '11 at 13:06Shahbaz5,2251317 asked Nov 16 '11 at 12:58David Given2,812318 35% accept rate.

– Brian Roach Nov 16 '11 at 13:03 There's no inherent problem with fork() in a multithreaded program, bar it might be a tad inefficient for large memory hungry and busy threaded applicatons. – nos Nov 16 '11 at 13:07 system() works by doing fork()/exec()! – David Given Nov 16 '11 at 13:24 2 The biggest issue with using fork() and threads is that when the fork() happens, all the other threads just vanish --- regardless of whether they're in critical sections or not.

And the state of locks, semaphores etc become undefined in the child. So if one thread was in the middle of a malloc(), and then the child calls malloc(), Horrible Things can happen (which I think was happening to me). In fact, I've restructured things so that I'm using vfork() and the only function the child ever calls it exec(), and I think my crash has stopped manifesting, but I'd still like an answer... – David Given Nov 16 '11 at 13:28.

Calling fork should be safe if you limit yourself to "raw" system calls (syscall(SYS_fork), syscalll(SYS_execve, ...), etc.). Call into any glibc routine, and you'll be in a lot of trouble. Calling vfork is not at all what you want: only the thread that called vfork is suspended, and other threads will continue to run (and in the same address space as the vforked child).

This is very likely to complicate your life. Calling clone directly is possible, but exceedingly tricky. We have an implementation that allows for safe forking of child processes from multithreaded apps (unfortunately not open source).

That code is very tricky, and surprisingly long.

Fork() and then an immediate exec() without any intervening code seems to work --- or at least, hasn't crashed yet... Thanks. – David Given Nov 21 '11 at 12:15.

Fork'ing multithreaded application is considered to be safe if you use only async-signal-safe operations. POSIX says: 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. Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork() calls. Posix_spawn() is not the best idea: It is also complicated to modify the environment of a multi-threaded process temporarily, since all threads must agree when it is safe for the environment to be changed.

However, this cost is only borne by those invocations of posix_spawn() and posix_spawnp() that use the additional functionality. Since extensive modifications are not the usual case, and are particularly unlikely in time-critical code, keeping much of the environment control out of posix_spawn() and posix_spawnp() is appropriate design. (see man posix_spawn) I guess you have problems with replicated from parent resources.

You may clean them up using pthread_atfork() handler (you use pthread, right? ). The other way is to use low level function for process creation called clone().

It gives you almost full control on what exactly child process should inherit from its parent. UPDATE Probably the simplest way to get rid of the problem is to change your fork'ing scheme. For example you can create a new process (fork) even before your program initializes all resources.

I.e. Call fork() in main() before you create all your threads. In child process setup a signal handler (for example for SIGUSR2 signal) and sleep.

When parent needs to exec some new process, it sends the SIGUSR2 signal to your child process. When child catches it, it calls fork/exec.

You can use > to write quotes. I edited your post :) – Shahbaz Nov 16 '11 at 13:48 @Shahbaz heh, it seems you updated it at the same time I did and your changes wasn't saved (fixed). – Dan Kruchinin Nov 16 '11 at 13:55 Thanks, but if you look at my question you'll see that I explicitly say that I can't create my new process before the threads start.

If you want the messy details, it's because my code runs as a dynamically loaded JNI object, and Java's already created a hundred threads before my code even loads... – David Given Nov 16 '11 at 14:58 @DavidGiven I'm not an expert in JNI and I expected that there's a way to do it. If there's no way to make a new process as early as possible, it's a problem, because there're no "thread safe" alternatives to fork/exec except clone (which is complicated one). If there're no alternative ways to get your task done, I'd suggest either to write separate daemon that does fork/exec and talk to it using IPC or to write linux kernel module that launches user-space process (see ibm.com/developerworks/linux/library/l-u...).

Of course ways I mentioned are hacks... – Dan Kruchinin Nov 16 '11 at 18:43.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions