diff options
Diffstat (limited to 'src/3rdparty/forkfd/forkfd.c')
-rw-r--r-- | src/3rdparty/forkfd/forkfd.c | 28 |
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 |