John, I think that the bodies of these functions should be wrapped
inside sigprocmask calls so that the signal handler is not called
unexpectedly. (generateChild contains the fork, execvp code).
Agree?
Questions.
1. In runBlocking, all SIGCHLD signals are blocked until after this
particular child has died and been reaped. Am I corect to say that
thereafter the signal handler will not receive a signal corresponding
to this particular child?
2. In runNonBlocking(), all SIGCHLD signals are blocked until after we
have performed some preliminary book-keeping in
ForkedcallsController::addCall. Am I correct to say that thereafter
the signal handler *will* receive a signal if the child failed to
start (failed execvp) but will not receive a signal if the fork
failed?
Angus
// Wait for child process to finish.
int ForkedProcess::runBlocking()
{
+ sigset_t newMask, oldMask;
+
+ sigemptyset(&oldMask);
+ sigemptyset(&newMask);
+ sigaddset(&newMask, SIGCHLD);
+
+ sigprocmask(SIG_BLOCK, &newMask, &oldMask);
+
retval_ = 0;
pid_ = generateChild();
if (pid_ <= 0) { // child or fork failed.
retval_ = 1;
return retval_;
}
retval_ = waitForChild();
+
+ sigprocmask(SIG_SETMASK, &oldMask, 0);
+
return retval_;
}
// Do not wait for child process to finish.
int ForkedProcess::runNonBlocking()
{
+ sigset_t newMask, oldMask;
+
+ sigemptyset(&oldMask);
+ sigemptyset(&newMask);
+ sigaddset(&newMask, SIGCHLD);
+
+ sigprocmask(SIG_BLOCK, &newMask, &oldMask);
+
retval_ = 0;
pid_ = generateChild();
if (pid_ <= 0) { // child or fork failed.
retval_ = 1;
return retval_;
}
// Non-blocking execution.
// Integrate into the Controller
ForkedcallsController & contr = ForkedcallsController::get();
contr.addCall(*this);
+
+ sigprocmask(SIG_SETMASK, &oldMask, 0);
+
return retval_;
}