diff options
author | Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> | 2023-01-12 10:58:51 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2023-02-01 08:42:11 -0300 |
commit | 2053c11331991818882f7cf023ed2ce4ff44b274 (patch) | |
tree | b1edaafb8036456c39bff1756ed8827922c0b3b5 /sysdeps/unix/sysv/linux/clone-internal.c | |
parent | 2290cf73cce1292d9345a8183fd29ae3994a9481 (diff) | |
download | glibc-2053c11331991818882f7cf023ed2ce4ff44b274.tar glibc-2053c11331991818882f7cf023ed2ce4ff44b274.tar.gz glibc-2053c11331991818882f7cf023ed2ce4ff44b274.tar.bz2 glibc-2053c11331991818882f7cf023ed2ce4ff44b274.zip |
linux: Add clone3 CLONE_CLEAR_SIGHAND optimization to posix_spawn
The clone3 flag resets all signal handlers of the child not set to
SIG_IGN to SIG_DFL. It allows to skip most of the sigaction calls
to setup child signal handling, where previously a posix_spawn
had to issue 2 times NSIG sigaction calls (one to obtain the current
disposition and another to set either SIG_DFL or SIG_IGN).
With POSIX_SPAWN_SETSIGDEF the child will setup the signal for the case
where the disposition is SIG_IGN.
The code must handle the fallback where clone3 is not available. This is
done by splitting __clone_internal_fallback from __clone_internal.
Checked on x86_64-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'sysdeps/unix/sysv/linux/clone-internal.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/clone-internal.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/sysdeps/unix/sysv/linux/clone-internal.c b/sysdeps/unix/sysv/linux/clone-internal.c index a8611772a2..e125c9125e 100644 --- a/sysdeps/unix/sysv/linux/clone-internal.c +++ b/sysdeps/unix/sysv/linux/clone-internal.c @@ -44,27 +44,15 @@ _Static_assert (sizeof (struct clone_args) == CLONE_ARGS_SIZE_VER2, "sizeof (struct clone_args) != CLONE_ARGS_SIZE_VER2"); int -__clone_internal (struct clone_args *cl_args, - int (*func) (void *arg), void *arg) +__clone_internal_fallback (struct clone_args *cl_args, + int (*func) (void *arg), void *arg) { - int ret; -#ifdef HAVE_CLONE3_WRAPPER - /* Try clone3 first. */ - int saved_errno = errno; - ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); - if (ret != -1 || errno != ENOSYS) - return ret; - - /* NB: Restore errno since errno may be checked against non-zero - return value. */ - __set_errno (saved_errno); -#endif - /* Map clone3 arguments to clone arguments. NB: No need to check invalid clone3 specific bits in flags nor exit_signal since this is an internal function. */ int flags = cl_args->flags | cl_args->exit_signal; void *stack = cast_to_pointer (cl_args->stack); + int ret; #ifdef __ia64__ ret = __clone2 (func, stack, cl_args->stack_size, @@ -88,4 +76,23 @@ __clone_internal (struct clone_args *cl_args, return ret; } + +int +__clone_internal (struct clone_args *cl_args, + int (*func) (void *arg), void *arg) +{ +#ifdef HAVE_CLONE3_WRAPPER + int saved_errno = errno; + int ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); + if (ret != -1 || errno != ENOSYS) + return ret; + + /* NB: Restore errno since errno may be checked against non-zero + return value. */ + __set_errno (saved_errno); +#endif + + return __clone_internal_fallback (cl_args, func, arg); +} + libc_hidden_def (__clone_internal) |