This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: posix_spawn and vfork
On 07/05/2019 05:50, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>>> If we want to go this route, I'd suggest something like this as a
>>> building block:
>>>
>>> pid_t clone_samestack (unsigned int flags, void (*action) (void *)
>>> void *closure);
>>>
>>> and it would be a fatal error if ACTION (CLOSURE) returns. The function
>>> would fail with EINVAL if FLAGS contained CLONE_VM without CLONE_VFORK.
>>>
>>> Once we have that, the need for explicit stack management goes away.
>>
>> But would it just a shim wrapper over clone (to handle the required kABI)
>> as vfork currently is or something more sane as posix_spawn to work
>> correctly along libc? Also, would be just an internal interface or
>> a possible extension?
>
> I think it would make sense to start out with the thin wrapper, and then
> build the safer vfork abstraction on top of that.
>
>> Because for a clone wrapper, I think would be simpler to just make using
>> clone instead by allowing it accept a null stack input.
>>
>> ---
>> struct wrapper_argument
>> {
>> void (*action) (void *) fn;
>> void *arg;
>> };
>>
>> void wrapper (void *input)
>> {
>> struct wrapper_argument *arg = input;
>> arg->fn (arg->arg);
>> abort ();
>> }
>>
>> pid_t clone_samestack (unsigned int flags, void (*action) (void *)
>> void *closure)
>> {
>> int clone_flags = CLONE_VM | CLONE_VFORK | SIGCHLD;
>> #ifndef __ia64__
>> return clone (wrapper, NULL, clone_flags,
>> &(struct wrapper_argument) { action, closure }));
>> #else
>> return __clone2 (wrapper, NULL, sizeof stack,
>> &(struct wrapper_argument) { action, closure }));
>> #endif
>> }
>>
>> ---
>>
>> It also wouldn't require potentially another arch-specific assembly
>> implementation.
>
> For the x86-64 and i386 implementations, it's not just about removing
> the NULL check. I think we will need different trampoline functions,
> with different unwinding data. At that point, we can just rewrite the
> whole function.
It is still better than add *another* assembly required implementation that
would need to be implemented or adjusted for every port.
>
>> However my main issue with such interface where is reuses the stack from
>> parent process is how safe this construction is. That's why I think the
>> xfork symbol, which either allocates a pre-defined stack or accepts a
>> user-define one (as for sigaltstack) should be safer and play along
>> libc interfaces better (it could either share some code with posix_spawn).
>
> I think it boils down to whether the parent thread is reliably stopped
> during vfork (if it is not implemented as fork). I have not seen any
> indication so far that the blocking is unreliable in current (3.x)
> kernels.
My problem is the blurry state the new process is created due the CLONE_VM,
where although it stops the calling process, it still needs to handle shared
states being modified by standard functions (such as malloc) or even with
more complicated states (dynamic loading, dynamic binding, etc).
It gets even more complicate when we started to handle more complex scenarios,
such cancellation, unwinding, non async-safe functions, etc.
>
> In contrast, when sizing the separate stack, you need to make educated
> guesses about ld.so stack space requirements. Ideally, you would also
> add a guard page. The new stack may need to be communicated to memory
> debuggers. And so on. All in all, stack switching seems more risky to
> me.
For generic case I do agree dynamic binding does impose some issues
(although golang with split-stack already set some precedent that
it somewhat feasible to pick a stack size for this).
In any case, I think we are deviating to the point of what would be the
real usercases for a vfork-like interface. Currently AFAIK vfork is
used mainly as a replacement of fork for performance-wise improvement in
process spawning. It is something that I do think it would be better
served with posix_spawn and well-thought extension (as we are doing
in latest glibc releases).
So do you think we will different vfork scenarios that posix_spawn is
not a possible fit (even with extended attribute or file actions)?