When I call vfork (), can I call any exec * () function, or do I need to call execve ()?

On the Linux manual page :

The vfork() function has the same effect as fork(2) , except that the behavior is undefined if the process [...] calls any other function before successfully calling [...] one of the exec(3) family functions.

This suggests that calling any exec*() function after vfork() is acceptable. However, later on the man page he says specifically:

In particular, a programmer cannot rely on a parent who remains locked until the child [...] calls execve(2) [...].

execve(2) is reused on the manual page, and its use assumes that this is the only exec -type function acceptable after vfork() .

So, why is execve highlighted here, and is it safe to call other exec -type functions (e.g. execlp )?

+6
source share
3 answers

You must call execve . There is no guarantee that no other exec-family functions will perform actions that would be unsafe after vfork . For instance:

  • execl can allocate memory for an argument list. This should be safe for the asynchronous signal, which means it is unlikely to use malloc , but even if this does not happen, it will not be able to free the allocated memory (which exists in the parent memory space) after the underlying execve , so it will (at best) a memory leak in the parent, unless it succeeds in constructing a list of arguments on the stack.

  • execvp must gain access to the environment to perform a path search, and also to create concatenated paths in order to go to execve . The latter may require isolation, and the former can do all kinds of unsafe things after vfork (note: execvp is not even safe for an asynchronous signal).

and etc.

Indeed, you simply should not use vfork . It is almost impossible to make its use safe. In particular, this is unsafe in any program that uses signal handlers, since the signal handler can run in the child element when it shares the parent memory if you do not block all signals (in which case the child inherits a completely blocked signal mask after exec, which is almost certainly not what you want).

If you are looking for a more efficient alternative to fork , use posix_spawn .

+5
source

On Linux, all exec* functions are actually shell library functions on top of execve syscall. Therefore, by calling execlp , you are also calling execve .

+1
source

After reading the manual, it again becomes clear that there are two vfork descriptions:

The POSIX standard description states that after vfork , one of the exec(3) functions must be called.

The Linux description says that after vfork you need to call execve(2) (and only execve ).

It’s not clear to me whether the POSIX standard description corresponds to the corresponding implementation that allows calling any of the exec functions. One possible indication of the standard description is that the implementation can decide which exec functions are allowed (and only requires at least one of them to be enabled after vfork ).

In any case, it is clear that Linux allows execve (and only execve *) to be called after vfork . The POSIX standard may allow other exec functions, but Linux does not work.

* Well, of course, it can call _exit too, but I ignore _exit in this Q & A.

0
source

Source: https://habr.com/ru/post/970844/


All Articles