summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/forkfd
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-02-17 10:10:39 -0800
committerThiago Macieira <thiago.macieira@intel.com>2017-02-26 05:53:27 +0000
commit1b81f931839229fbc2e1769d2d3ea62a108727c4 (patch)
tree637fb0482f74c5cffb0b2bb72138c378353f1e9b /src/3rdparty/forkfd
parente3bcab935c9fe37b344394c3ee8afd6773a8cd7e (diff)
forkfd: use SA_SIGINFO to pass extra information to chained handlers
This existed in QProcess before forkfd, but was lost in the port to it (commit 1814142b7a11befab315bf3f9d91c4ffbf56ef3e). The original QProcess fix was done in 97279d05822a70da1fb3dab083d823a5f5a008fe. Task-number: QTBUG-57584 Change-Id: Ibc5c715fda334a75bd2efffd14a425871f3162b5 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/3rdparty/forkfd')
-rw-r--r--src/3rdparty/forkfd/forkfd.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index e57d9aa1e0..309458a3a7 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,18 @@ 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_flags & SA_SIGINFO)
+ old_sigaction.sa_sigaction(signum, handler_info, handler_context);
+ else if (old_sigaction.sa_handler != SIG_IGN && old_sigaction.sa_handler != SIG_DFL)
+ old_sigaction.sa_handler(signum);
if (ffd_atomic_load(&forkfd_status, FFD_ATOMIC_RELAXED) == 1) {
/* is this one of our children? */
@@ -317,9 +328,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 +417,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 +461,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