Blame SOURCES/nss-softokn-3.16-block-sigchld.patch

6fbbf4
diff -up ./nss/lib/freebl/shvfy.c.block_sigchld ./nss/lib/freebl/shvfy.c
6fbbf4
--- ./nss/lib/freebl/shvfy.c.block_sigchld	2014-10-23 10:38:01.494609227 -0700
6fbbf4
+++ ./nss/lib/freebl/shvfy.c	2014-10-23 10:44:35.395609071 -0700
6fbbf4
@@ -45,8 +45,50 @@
6fbbf4
 #include <stdlib.h>
6fbbf4
 #include <unistd.h>
6fbbf4
 #include <fcntl.h>
6fbbf4
-#include <sys/wait.h>
6fbbf4
 #include <sys/stat.h>
6fbbf4
+#include <errno.h>
6fbbf4
+
6fbbf4
+#define __USE_POSIX199309 1 /* need to use posix signal handler */
6fbbf4
+#include <signal.h>
6fbbf4
+#include <sys/wait.h> /* must be after signal.h */
6fbbf4
+
6fbbf4
+
6fbbf4
+/*
6fbbf4
+ * handler to block our sigchld call to keep from confusing parent apps
6fbbf4
+ */
6fbbf4
+static struct sigaction parent_handler;
6fbbf4
+static int child_pid = 0;
6fbbf4
+
6fbbf4
+static void
6fbbf4
+handle_sigchld(int signum, siginfo_t *sinfo, void *utcx)
6fbbf4
+{
6fbbf4
+    int status;
6fbbf4
+    int save_errno = errno;
6fbbf4
+    int ret;
6fbbf4
+
6fbbf4
+    if ((signum == SIGCHLD) && (sinfo->si_pid == child_pid)) {
6fbbf4
+	waitpid(sinfo->si_pid,&status, 0);
6fbbf4
+	errno = save_errno;
6fbbf4
+	return;
6fbbf4
+    }
6fbbf4
+
6fbbf4
+
6fbbf4
+    /* call parent, first set the parents mask */
6fbbf4
+    ret = sigprocmask(SIG_BLOCK, &parent_handler.sa_mask, NULL);
6fbbf4
+    errno = save_errno; /* restore previous errno. allow parent to change
6fbbf4
+			 * errno if it needs to */
6fbbf4
+    if (ret < 0) {
6fbbf4
+	return;
6fbbf4
+    }
6fbbf4
+    /* now call the parent */
6fbbf4
+    if (parent_handler.sa_flags & SA_SIGINFO) {
6fbbf4
+	(*parent_handler.sa_sigaction)(signum, sinfo, utcx);
6fbbf4
+    } else {
6fbbf4
+	(*parent_handler.sa_handler)(signum);
6fbbf4
+    }
6fbbf4
+    /* libc/kernel should restore our mask as this point, so we don't
6fbbf4
+     * need to restore the mask we set above. */
6fbbf4
+}
6fbbf4
 
6fbbf4
 /*
6fbbf4
  * This function returns an NSPR PRFileDesc * which the caller can read to
6fbbf4
@@ -72,6 +114,8 @@ bl_OpenUnPrelink(const char *shName, int
6fbbf4
     pid_t child;
6fbbf4
     int argc = 0, argNext = 0;
6fbbf4
     struct stat statBuf;
6fbbf4
+    struct sigaction our_handler;
6fbbf4
+    sigset_t inMask,outMask;
6fbbf4
     int pipefd[2] = {-1,-1};
6fbbf4
     int ret;
6fbbf4
 
6fbbf4
@@ -155,6 +199,25 @@ bl_OpenUnPrelink(const char *shName, int
6fbbf4
 	goto loser;
6fbbf4
     }
6fbbf4
 
6fbbf4
+    child_pid = 0;
6fbbf4
+    our_handler.sa_flags = SA_SIGINFO;
6fbbf4
+    our_handler.sa_sigaction = handle_sigchld;
6fbbf4
+    sigemptyset(&our_handler.sa_mask);
6fbbf4
+    ret = sigaction(SIGCHLD, &our_handler, &parent_handler);
6fbbf4
+    if (ret < 0) {
6fbbf4
+	goto loser;
6fbbf4
+    }
6fbbf4
+
6fbbf4
+    /* don't accept a sigchild until we've set out child pid */
6fbbf4
+    sigemptyset(&inMask);
6fbbf4
+    sigemptyset(&outMask);
6fbbf4
+    sigaddset(&inMask,SIGCHLD);
6fbbf4
+    ret = sigprocmask(SIG_BLOCK, &inMask, &outMask);
6fbbf4
+    if (ret < 0) {
6fbbf4
+	sigaction(SIGCHLD, &parent_handler, NULL);
6fbbf4
+	goto loser;
6fbbf4
+    }
6fbbf4
+
6fbbf4
     /* use vfork() so we don't trigger the pthread_at_fork() handlers */
6fbbf4
     child = vfork();
6fbbf4
     if (child < 0) goto loser;
6fbbf4
@@ -174,6 +237,8 @@ bl_OpenUnPrelink(const char *shName, int
6fbbf4
 	/* avoid at_exit() handlers */
6fbbf4
 	_exit(1); /* shouldn't reach here except on an error */
6fbbf4
     }
6fbbf4
+    child_pid = child;
6fbbf4
+    sigprocmask(SIG_SETMASK, &outMask, 0); /* child is set,accept signals now */
6fbbf4
     close(pipefd[1]);
6fbbf4
     pipefd[1] = -1;
6fbbf4
 
6fbbf4
@@ -218,6 +283,9 @@ bl_CloseUnPrelink( PRFileDesc *file, int
6fbbf4
     /* reap the child */
6fbbf4
     if (pid) {
6fbbf4
 	waitpid(pid, NULL, 0);
6fbbf4
+	/* restore the parent handler */
6fbbf4
+	sigaction(SIGCHLD, &parent_handler, NULL);
6fbbf4
+	child_pid = 0;
6fbbf4
     }
6fbbf4
 }
6fbbf4
 #endif