From ad045176238549c3267fff3e8c0014dd5e9ffbdf Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Sat, 2 Feb 2008 00:17:35 +0000 Subject: Block signals to avoid fork /signal races. --- src/librc/librc.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'src/librc/librc.c') diff --git a/src/librc/librc.c b/src/librc/librc.c index dbbdbb5..1cd3eec 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -32,6 +32,7 @@ const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include "librc.h" +#include #define SOFTLEVEL RC_SVCDIR "/softlevel" @@ -575,6 +576,10 @@ static pid_t _exec_service (const char *service, const char *arg) char *file; char *fifo; pid_t pid = -1; + sigset_t empty; + sigset_t full; + sigset_t old; + struct sigaction sa; file = rc_service_resolve (service); if (! exists (file)) { @@ -593,13 +598,37 @@ static pid_t _exec_service (const char *service, const char *arg) return (-1); } - if ((pid = vfork ()) == 0) { + /* We need to block signals until we have forked */ + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + sigemptyset (&empty); + sigfillset (&full); + sigprocmask (SIG_SETMASK, &full, &old); + + if ((pid = fork ()) == 0) { + /* Restore default handlers */ + sigaction (SIGCHLD, &sa, NULL); + sigaction (SIGHUP, &sa, NULL); + sigaction (SIGINT, &sa, NULL); + sigaction (SIGQUIT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + sigaction (SIGUSR1, &sa, NULL); + sigaction (SIGWINCH, &sa, NULL); + + /* Unmask signals */ + sigprocmask (SIG_SETMASK, &empty, NULL); + + /* Safe to run now */ execl (file, file, arg, (char *) NULL); - fprintf (stderr, "unable to exec `%s': %s\n", file, strerror (errno)); + fprintf (stderr, "unable to exec `%s': %s\n", + file, strerror (errno)); unlink (fifo); _exit (EXIT_FAILURE); } + sigprocmask (SIG_SETMASK, &old, NULL); + free (fifo); free (file); -- cgit v1.2.3