summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2025-01-18 12:59:57 -0500
committerTavian Barnes <tavianator@tavianator.com>2025-01-18 12:59:57 -0500
commitaf207e702148e5c9ae08047d7a2dce6394653b62 (patch)
tree378399af332c41f9580cad57707be76e0d1e3264
parent62928ddf80fea0291cf40d95877bb5b6f9d110c9 (diff)
downloadbfs-af207e702148e5c9ae08047d7a2dce6394653b62.tar.xz
xspawn: Unblock signals between fork() and exec()
Otherwise the child process runs with all signals blocked. Fixes: 423cfa4 ("xspawn: Mask signals before fork()")
-rw-r--r--src/xspawn.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/xspawn.c b/src/xspawn.c
index b3eed79..3fa4e60 100644
--- a/src/xspawn.c
+++ b/src/xspawn.c
@@ -8,6 +8,7 @@
#include "bfstd.h"
#include "diag.h"
#include "list.h"
+#include "sighook.h"
#include <errno.h>
#include <fcntl.h>
@@ -535,7 +536,7 @@ static bool bfs_use_posix_spawn(const struct bfs_resolver *res, const struct bfs
/** Actually exec() the new process. */
_noreturn
-static void bfs_spawn_exec(struct bfs_resolver *res, const struct bfs_spawn *ctx, char **argv, char **envp, int pipefd[2]) {
+static void bfs_spawn_exec(struct bfs_resolver *res, const struct bfs_spawn *ctx, char **argv, char **envp, const sigset_t *mask, int pipefd[2]) {
xclose(pipefd[0]);
for_slist (const struct bfs_spawn_action, action, ctx) {
@@ -596,6 +597,18 @@ static void bfs_spawn_exec(struct bfs_resolver *res, const struct bfs_spawn *ctx
goto fail;
}
+ // Reset signal handlers to their original values before we unblock
+ // signals, so that handlers don't run in both the parent and the child
+ if (sigreset() != 0) {
+ goto fail;
+ }
+
+ // Restore the original signal mask for the child process
+ errno = pthread_sigmask(SIG_SETMASK, mask, NULL);
+ if (errno != 0) {
+ goto fail;
+ }
+
execve(res->exe, argv, envp);
fail:;
@@ -635,7 +648,7 @@ static pid_t bfs_fork_spawn(struct bfs_resolver *res, const struct bfs_spawn *ct
#endif
if (pid == 0) {
// Child
- bfs_spawn_exec(res, ctx, argv, envp, pipefd);
+ bfs_spawn_exec(res, ctx, argv, envp, &old_mask, pipefd);
}
// Restore the original signal mask