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/spawni.c | |
parent | 2290cf73cce1292d9345a8183fd29ae3994a9481 (diff) | |
download | glibc-2053c11331991818882f7cf023ed2ce4ff44b274.tar.gz glibc-2053c11331991818882f7cf023ed2ce4ff44b274.tar.xz 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/spawni.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/spawni.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c index a1a14a58ae..bc321d4c58 100644 --- a/sysdeps/unix/sysv/linux/spawni.c +++ b/sysdeps/unix/sysv/linux/spawni.c @@ -66,6 +66,7 @@ struct posix_spawn_args ptrdiff_t argc; char *const *envp; int xflags; + bool use_clone3; int err; }; @@ -104,12 +105,11 @@ __spawni_child (void *arguments) const posix_spawnattr_t *restrict attr = args->attr; const posix_spawn_file_actions_t *file_actions = args->fa; - /* The child must ensure that no signal handler are enabled because it shared - memory with parent, so the signal disposition must be either SIG_DFL or - SIG_IGN. It does by iterating over all signals and although it could - possibly be more optimized (by tracking which signal potentially have a - signal handler), it might requires system specific solutions (since the - sigset_t data type can be very different on different architectures). */ + /* The child must ensure that no signal handler is enabled because it + shares memory with parent, so all signal dispositions must be either + SIG_DFL or SIG_IGN. If clone3/CLONE_CLEAR_SIGHAND is used, there is + only the need to set the defined signals POSIX_SPAWN_SETSIGDEF to + SIG_DFL; otherwise, the code iterates over all signals. */ struct sigaction sa; memset (&sa, '\0', sizeof (sa)); @@ -122,7 +122,7 @@ __spawni_child (void *arguments) { sa.sa_handler = SIG_DFL; } - else if (__sigismember (&hset, sig)) + else if (!args->use_clone3 && __sigismember (&hset, sig)) { if (is_internal_signal (sig)) sa.sa_handler = SIG_IGN; @@ -382,12 +382,25 @@ __spawnix (pid_t * pid, const char *file, for instance). */ struct clone_args clone_args = { - .flags = CLONE_VM | CLONE_VFORK, + /* Unsupported flags like CLONE_CLEAR_SIGHAND will be cleared up by + __clone_internal_fallback. */ + .flags = CLONE_CLEAR_SIGHAND | CLONE_VM | CLONE_VFORK, .exit_signal = SIGCHLD, .stack = (uintptr_t) stack, .stack_size = stack_size, }; - new_pid = __clone_internal (&clone_args, __spawni_child, &args); +#ifdef HAVE_CLONE3_WRAPPER + args.use_clone3 = true; + new_pid = __clone3 (&clone_args, sizeof (clone_args), __spawni_child, + &args); + /* clone3 was added in 5.3 and CLONE_CLEAR_SIGHAND in 5.5. */ + if (new_pid == -1 && (errno == ENOSYS || errno == EINVAL)) +#endif + { + args.use_clone3 = false; + new_pid = __clone_internal_fallback (&clone_args, __spawni_child, + &args); + } /* It needs to collect the case where the auxiliary process was created but failed to execute the file (due either any preparation step or |