diff options
Diffstat (limited to 'src/xspawn.c')
-rw-r--r-- | src/xspawn.c | 65 |
1 files changed, 36 insertions, 29 deletions
diff --git a/src/xspawn.c b/src/xspawn.c index 347625d..33e5a4a 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -1,13 +1,15 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xspawn.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" +#include "diag.h" #include "list.h" #include <errno.h> #include <fcntl.h> +#include <signal.h> #include <stdlib.h> #include <string.h> #include <sys/resource.h> @@ -212,7 +214,7 @@ int bfs_spawn_adddup2(struct bfs_spawn *ctx, int oldfd, int newfd) { * but macOS and NetBSD resolve the PATH *before* file_actions (because there * posix_spawn() is its own syscall). */ -#define BFS_POSIX_SPAWNP_AFTER_FCHDIR !(__APPLE__ || __NetBSD_Prereq__(10, 0, 0)) +#define BFS_POSIX_SPAWNP_AFTER_FCHDIR !(__APPLE__ || __NetBSD__) int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { struct bfs_spawn_action *action = bfs_spawn_action(BFS_SPAWN_FCHDIR); @@ -220,29 +222,15 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { return -1; } -#ifndef BFS_HAS_POSIX_SPAWN_FCHDIR -# define BFS_HAS_POSIX_SPAWN_FCHDIR __NetBSD_Prereq__(10, 0, 0) -#endif - -#ifndef BFS_HAS_POSIX_SPAWN_FCHDIR_NP -# if __GLIBC__ -# define BFS_HAS_POSIX_SPAWN_FCHDIR_NP __GLIBC_PREREQ(2, 29) -# elif __ANDROID__ -# define BFS_HAS_POSIX_SPAWN_FCHDIR_NP (__ANDROID_API__ >= 34) -# else -# define BFS_HAS_POSIX_SPAWN_FCHDIR_NP (__linux__ || __FreeBSD__ || __APPLE__) -# endif -#endif - -#if BFS_HAS_POSIX_SPAWN_FCHDIR -# define BFS_POSIX_SPAWN_FCHDIR posix_spawn_file_actions_addfchdir -#elif BFS_HAS_POSIX_SPAWN_FCHDIR_NP -# define BFS_POSIX_SPAWN_FCHDIR posix_spawn_file_actions_addfchdir_np +#if BFS_HAS_POSIX_SPAWN_ADDFCHDIR +# define BFS_POSIX_SPAWN_ADDFCHDIR posix_spawn_file_actions_addfchdir +#elif BFS_HAS_POSIX_SPAWN_ADDFCHDIR_NP +# define BFS_POSIX_SPAWN_ADDFCHDIR posix_spawn_file_actions_addfchdir_np #endif #if _POSIX_SPAWN > 0 && defined(BFS_POSIX_SPAWN_FCHDIR) if (ctx->flags & BFS_SPAWN_USE_POSIX) { - errno = BFS_POSIX_SPAWN_FCHDIR(&ctx->actions, fd); + errno = BFS_POSIX_SPAWN_ADDFCHDIR(&ctx->actions, fd); if (errno != 0) { free(action); return -1; @@ -604,30 +592,49 @@ static pid_t bfs_fork_spawn(struct bfs_resolver *res, const struct bfs_spawn *ct return -1; } + // Block signals before fork() so handlers don't run in the child + sigset_t new_mask; + if (sigfillset(&new_mask) != 0) { + goto fail; + } + sigset_t old_mask; + errno = pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); + if (errno != 0) { + goto fail; + } + pid_t pid = fork(); - if (pid < 0) { - close_quietly(pipefd[1]); - close_quietly(pipefd[0]); - return -1; - } else if (pid == 0) { + if (pid == 0) { // Child bfs_spawn_exec(res, ctx, argv, envp, pipefd); } - // Parent + // Restore the original signal mask + int ret = pthread_sigmask(SIG_SETMASK, &old_mask, NULL); + bfs_everify(ret == 0, "pthread_sigmask()"); + + if (pid < 0) { + // fork() failed + goto fail; + } + xclose(pipefd[1]); int error; ssize_t nbytes = xread(pipefd[0], &error, sizeof(error)); xclose(pipefd[0]); if (nbytes == sizeof(error)) { - int wstatus; - xwaitpid(pid, &wstatus, 0); + xwaitpid(pid, NULL, 0); errno = error; return -1; } return pid; + +fail: + close_quietly(pipefd[1]); + close_quietly(pipefd[0]); + return -1; } /** Call the right bfs_spawn() implementation. */ |