system() using vfork() or posix_spawn() and libthr

David Xu davidxu at freebsd.org
Tue Aug 14 09:17:18 UTC 2012


On 2012/08/14 16:18, Konstantin Belousov wrote:
> On Tue, Aug 14, 2012 at 12:42:15PM +0800, David Xu wrote:
>> I simply duplicated idea from OpenSolaris, here is my patch
>> which has similar feature as your patch, and it also tries to
>> prevent vforked child from corrupting parent's data:
>> http://people.freebsd.org/~davidxu/patch/libthr-vfork.diff
> You shall not return from vfork() frame in the child. Otherwise, the
> same frame is appears to be destroyed in parent, and parent dies. More
> often on !x86, but right combination of events on x86 is deadly too.
> If pid or curthread local variables are spilled into stack save area,
> then child will override them, and e.g. parent could see pid == 0,
> returning it to caller.
>
> This was the reason why I went to asm wrapper for vfork.
>
OK.

> Also, it seems that in mt process, malloc and rtld are still broken,
> or am I missing something ?

I will not call it as broken, malloc and rtld are working properly.
vfork is not a normal function, for MT process, fork() is even
very special too.

POSIX says a lot about multi-threaded:
http://pubs.opengroup.org/onlinepubs/000095399/functions/fork.html

I quoted some POSIX document here:
 > 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. [THR]   Fork
 > handlers may be established by means of the pthread_atfork() function
 > in order to maintain application invariants across fork() calls.

This means child process should only do very simple things, and
quickly call execv().

For mt process, fork() is already a very complicated problem,
one of problems I still remembered is that when fork() is called in
signal handler, should the thread library execute pthread_atfork
handler ?  if it should do, but none of lock is async-signal safe,
though our internal rwlock allows to be used in signal handler,
but it is not supported by POSIX.
Also are those atfork handler prepared to be executed in signal
handler ? it is undefined. POSIX had opened a door here.
Above is one of complicated problem, the vfork is even more
restrictive than fork().
If it is possible, I would avoid such a complicated problem
which vfork() would cause.

Regards,
David Xu


More information about the freebsd-hackers mailing list