diff options
| author | Roy Marples <roy@marples.name> | 2008-02-02 00:17:35 +0000 | 
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2008-02-02 00:17:35 +0000 | 
| commit | ad045176238549c3267fff3e8c0014dd5e9ffbdf (patch) | |
| tree | 8332746190f8e9fc47007090a3beac0a64d133c6 /src/librc | |
| parent | fef5d0af591c6c8a91f69bba5e62c99df1a732c9 (diff) | |
| download | openrc-ad045176238549c3267fff3e8c0014dd5e9ffbdf.tar.xz | |
Block signals to avoid fork /signal races.
Diffstat (limited to 'src/librc')
| -rw-r--r-- | src/librc/librc.c | 33 | 
1 files changed, 31 insertions, 2 deletions
| diff --git a/src/librc/librc.c b/src/librc/librc.c index dbbdbb5e..1cd3eec5 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 <signal.h>  #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); | 
