summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Pfaff <tpfaff@gmx.net>2010-12-03 14:01:28 -0600
committerWilliam Hubbs <williamh@gentoo.org>2010-12-03 14:01:28 -0600
commit062223a5df25a3b6f4d6c99580851e7daef70e8a (patch)
treec08c00f3a815e3d9a0ded2b78a7a2f05d5e02dcb
parent18064e19f6286595b81ef456dd23f453ff50dd5e (diff)
downloadopenrc-062223a5df25a3b6f4d6c99580851e7daef70e8a.tar.gz
openrc-062223a5df25a3b6f4d6c99580851e7daef70e8a.tar.bz2
openrc-062223a5df25a3b6f4d6c99580851e7daef70e8a.tar.xz
Avoid race condition in runscript (bug #319865)
Under normal conditions, runscript creates one child and waits for its termination, which is signaled by a pipe write from the SIGCHLD sighandler. When running killprocs however more than one SIGHCLD signal is generated, at least on all of my amd64 boxes running on real hardware and in vmware. When the first SIGCHLD occurs svc_exec leaves the loop and closes the pipe. Subsequent SIGCHLDs during the close can lead to a race condition and create an EBADF error in the pipe write (pipe is closed but the file handle is still != -1). We avoid this by blocking SIGHCHLD during the pipe close.
-rw-r--r--src/rc/runscript.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/rc/runscript.c b/src/rc/runscript.c
index e07cf58..f3f0517 100644
--- a/src/rc/runscript.c
+++ b/src/rc/runscript.c
@@ -350,6 +350,8 @@ svc_exec(const char *arg1, const char *arg2)
size_t bytes;
bool prefixed = false;
int slave_tty;
+ sigset_t sigchldmask;
+ sigset_t oldmask;
/* Setup our signal pipe */
if (pipe(signal_pipe) == -1)
@@ -439,10 +441,17 @@ svc_exec(const char *arg1, const char *arg2)
}
free(buffer);
+
+ sigemptyset (&sigchldmask);
+ sigaddset (&sigchldmask, SIGCHLD);
+ sigprocmask (SIG_BLOCK, &sigchldmask, &oldmask);
+
close(signal_pipe[0]);
close(signal_pipe[1]);
signal_pipe[0] = signal_pipe[1] = -1;
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+
if (master_tty >= 0) {
/* Why did we do this? */
/* signal (SIGWINCH, SIG_IGN); */