Fix sigchld-Handler
Changed the sigchld-Handler such that the SA_SIGINFO flag is handeled correctly. Furthermore the signal mask is preserved such that the original signal handler is not interrupted when not allowed. Task-number: QTBUG-32979 Change-Id: Iec7663e7289ea5d95155f52cf8788ebf646cfabd Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
ddecbae5e1
commit
97279d0582
@ -121,18 +121,34 @@ static const int errorBufferMax = 512;
|
||||
|
||||
static int qt_qprocess_deadChild_pipe[2];
|
||||
static struct sigaction qt_sa_old_sigchld_handler;
|
||||
static void qt_sa_sigchld_handler(int signum)
|
||||
static void qt_sa_sigchld_sigaction(int signum, siginfo_t *info, void *context)
|
||||
{
|
||||
// *Never* use the info or contect variables in this function
|
||||
// (except for passing them to the next signal in the chain).
|
||||
// We cannot be sure if another library or if the application
|
||||
// installed a signal handler for SIGCHLD without SA_SIGINFO
|
||||
// and fails to pass the arguments to us. If they do that,
|
||||
// these arguments contain garbage and we'd most likely crash.
|
||||
|
||||
qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
|
||||
#if defined (QPROCESS_DEBUG)
|
||||
fprintf(stderr, "*** SIGCHLD\n");
|
||||
#endif
|
||||
|
||||
// load it as volatile
|
||||
void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler;
|
||||
// load as volatile
|
||||
volatile struct sigaction *vsa = &qt_sa_old_sigchld_handler;
|
||||
|
||||
if (qt_sa_old_sigchld_handler.sa_flags & SA_SIGINFO) {
|
||||
void (*oldAction)(int, siginfo_t *, void *) = vsa->sa_sigaction;
|
||||
|
||||
oldAction(signum, info, context);
|
||||
} else {
|
||||
void (*oldAction)(int) = vsa->sa_handler;
|
||||
|
||||
if (oldAction && oldAction != SIG_IGN)
|
||||
oldAction(signum);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void add_fd(int &nfds, int fd, fd_set *fdset)
|
||||
{
|
||||
@ -197,10 +213,16 @@ QProcessManager::QProcessManager()
|
||||
|
||||
// set up the SIGCHLD handler, which writes a single byte to the dead
|
||||
// child pipe every time a child dies.
|
||||
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = qt_sa_sigchld_handler;
|
||||
action.sa_flags = SA_NOCLDSTOP;
|
||||
// use the old handler as template, i.e., preserve the signal mask
|
||||
// otherwise the original signal handler might be interrupted although it
|
||||
// was marked to never be interrupted
|
||||
::sigaction(SIGCHLD, NULL, &action);
|
||||
action.sa_sigaction = qt_sa_sigchld_sigaction;
|
||||
// set the SA_SIGINFO flag such that we can use the three argument handler
|
||||
// function
|
||||
action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
|
||||
::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
|
||||
|
||||
processManagerInstance = this;
|
||||
@ -225,7 +247,7 @@ QProcessManager::~QProcessManager()
|
||||
|
||||
struct sigaction currentAction;
|
||||
::sigaction(SIGCHLD, 0, ¤tAction);
|
||||
if (currentAction.sa_handler == qt_sa_sigchld_handler) {
|
||||
if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) {
|
||||
::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user