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_; }