summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/forkfd/forkfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/forkfd/forkfd.c')
-rw-r--r--src/3rdparty/forkfd/forkfd.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index e57d9aa1e0..8113fdb9e7 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -281,7 +281,7 @@ static void notifyAndFreeInfo(Header *header, ProcessInfo *entry,
freeInfo(header, entry);
}
-static void sigchld_handler(int signum)
+static void sigchld_handler(int signum, siginfo_t *handler_info, void *handler_context)
{
/*
* This is a signal handler, so we need to be careful about which functions
@@ -289,7 +289,20 @@ static void sigchld_handler(int signum)
* specification at:
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
*
+ * The handler_info and handler_context parameters may not be valid, if
+ * we're a chained handler from another handler that did not use
+ * SA_SIGINFO. Therefore, we must obtain the siginfo ourselves directly by
+ * calling waitid.
+ *
+ * But we pass them anyway. Let's call the chained handler first, while
+ * those two arguments have a chance of being correct.
*/
+ if (old_sigaction.sa_handler != SIG_IGN && old_sigaction.sa_handler != SIG_DFL) {
+ if (old_sigaction.sa_flags & SA_SIGINFO)
+ old_sigaction.sa_sigaction(signum, handler_info, handler_context);
+ else
+ old_sigaction.sa_handler(signum);
+ }
if (ffd_atomic_load(&forkfd_status, FFD_ATOMIC_RELAXED) == 1) {
/* is this one of our children? */
@@ -317,9 +330,8 @@ search_next_child:
waitid(P_ALL, 0, &info, WNOHANG | WNOWAIT | WEXITED);
if (info.si_pid == 0) {
/* there are no further un-waited-for children, so we can just exit.
- * But before, transfer control to the chained SIGCHLD handler.
*/
- goto chain_handler;
+ return;
}
for (i = 0; i < (int)sizeofarray(children.entries); ++i) {
@@ -407,12 +419,6 @@ search_arrays:
array = ffd_atomic_load(&array->header.nextArray, FFD_ATOMIC_ACQUIRE);
}
}
-
-#ifdef HAVE_WAITID
-chain_handler:
-#endif
- if (old_sigaction.sa_handler != SIG_IGN && old_sigaction.sa_handler != SIG_DFL)
- old_sigaction.sa_handler(signum);
}
static void ignore_sigpipe()
@@ -457,8 +463,8 @@ static void forkfd_initialize()
struct sigaction action;
memset(&action, 0, sizeof action);
sigemptyset(&action.sa_mask);
- action.sa_flags = SA_NOCLDSTOP;
- action.sa_handler = sigchld_handler;
+ action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
+ action.sa_sigaction = sigchld_handler;
/* ### RACE CONDITION
* The sigaction function does a memcpy from an internal buffer