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 1814142b7a). The original QProcess
fix was done in 97279d0582.

Task-number: QTBUG-57584
Change-Id: Ibc5c715fda334a75bd2efffd14a425871f3162b5
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Thiago Macieira 2017-02-17 10:10:39 -08:00
parent e3bcab935c
commit 1b81f93183
1 changed files with 15 additions and 11 deletions

View File

@ -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