From the Linux man page:
The
vfork()
function has the same effect asfork(2)
, except that the behavior is undefined if the process [...] calls any other function before successfully calling [...] one of theexec(3)
family of functions.
This suggests that calling any exec*()
function after vfork()
is acceptable. However, later in the man page it says specifically:
In particular, the programmer cannot rely on the parent remaining blocked until the child [...] calls
execve(2)
[...].
execve(2)
is used repeatedly in the man page, and its usage suggests that it's the only exec
-type function that is acceptable after vfork()
.
So why is execve
being singled out here, and am I safe to call other exec
-type functions (like execlp
)?
When vfork() is called in a multithreaded process, only the calling thread is suspended until the child terminates or executes a new program. This means that the child is sharing an address space with other running code.
The main reason is likely that the separation of the fork() and exec() steps allows arbitrary setup of the child environment to be done using other system calls.
This leads to more efficient memory usage. Question 7: [6 points] In terms of call-return behavior, how are the fork() and exec() system calls different from other system/function calls? Ans: fork(), if successful, returns twice – once in the parent and once in the child. Exec() never returns, if successful.
The vfork() function can be used to create new processes without fully copying the address space of the old process. If a forked process is simply going to call exec, the data space copied from the parent to the child by fork() is not used.
You must call execve
. There is no guarantee that any of the other exec-family functions do not perform actions which would be unsafe after vfork
. For example:
execl
may allocate memory for the argument list. It's required to be async-signal-safe, which means it's unlikely to use malloc
, but even if it doesn't, there's no way it could free the allocated memory (which exists in the parent's memory space) after the underlying execve
takes place, so it would (at best) leak memory in the parent unless it manages to construct the argument list on the stack.
execvp
needs to access the environment to perform a path search, and also needs to construct concatenated pathnames to pass to execve
. The latter may require allocation and the former may do all sorts of unsafe-after-vfork
things (note: execvp
is not even async-signal-safe).
etc.
Really you should simply not use vfork
. It's almost impossible to make its use safe. In particular it's unsafe in any program that's using signal handlers since the signal handler could run in the child while it's sharing the parent's memory unless you block all signals (and in that case the child would inherit a fully-blocked signal mask after exec, which is almost surely not what you want).
If you're looking for a more-efficient alternative to fork
, use posix_spawn
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With