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