I'm using my own spawn function and on Linux I'm using clone
with something like:
#define _GNU_SOURCE
#include <unistd.h>
#include <sched.h>
#include <signal.h>
pid_t run_kid(int Kid(void *), void *Arg, _Bool VForkEh)
{
#if __linux__
if(VForkEh){
char stack[1<<13];
return clone(Kid,stack+sizeof stack,
CLONE_VM|CLONE_VFORK|CLONE_CHILD_SETTID|SIGCHLD,
Arg, (void*)0/*partid,*/, (void*)0/*tls*/, (void*)0);
}
#endif
pid_t r; if (0==(r=fork())) _exit(Kid(Arg));
return r;
}
If you compile it on Linux and call it with VforkEh=1
, it will call clone and execute the Kid hook in the child while the parent is suspended as with vfork
(but without the problems of vfork
because of the dedicated stack).
You should then be able to execve
from the child, but keep in mind that because of the vfork
semantics, the memory of the parent and the child will be shared so you should avoid async-unsafe functions and undo errno
modifications if any.
http://git.musl-libc.org uses clone
in as similar way to implement posix_spawn (but it doesn't have to undo errno
-changes because it can use raw syscalls that don't set errno
at all).