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 (commitbb101814142b7a). The original QProcess fix was done in97279d0582. Task-number: QTBUG-57584 Change-Id: Ibc5c715fda334a75bd2efffd14a425871f3162b5 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
parent
e3bcab935c
commit
1b81f93183
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue