void ChildProcessTracker::attemptToReapProcess( const std::pair<PidType,ExitHandler>& process) { // non-blocking wait for the child int pid = process.first; int status; int result = waitPid(pid, &status); // reaped the child if (result == pid) { // confirm this was a real exit bool exited = false; if (WIFEXITED(status)) { exited = true; status = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { exited = true; } // if it was a real exit (as opposed to a SIGSTOP or SIGCONT) // then remove the pid from our table and fire the event if (exited) { // all done with this pid removeProcess(pid); // call exit handler if we have one ExitHandler exitHandler = process.second; if (exitHandler) exitHandler(pid, status); } else { boost::format fmt("Received SIGCHLD when child did not " "actually exit (pid=%1%, status=%2%"); LOG_WARNING_MESSAGE(boost::str(fmt % pid % status)); } } // error occured else if (result == -1) { Error error = systemError(errno, ERROR_LOCATION); error.addProperty("pid", pid); LOG_ERROR(error); } }
bool executeAndWait(const uid_t uid, const char* fname, const char* const* argv, int& status) { LOGD("Execute " << (uid == UNSPEC_UID ? "" : "as " + std::to_string(uid) + " ") << fname << argv); pid_t pid = ::fork(); if (pid == -1) { LOGE("Fork failed: " << getSystemErrorMessage()); return false; } if (pid == 0) { if (uid != UNSPEC_UID && ::setuid(uid) < 0) { LOGW("Failed to become uid(" << uid << "): " << getSystemErrorMessage()); ::_exit(EXIT_FAILURE); } ::execv(fname, const_cast<char* const*>(argv)); LOGE("execv(" << fname << ") failed: " << getSystemErrorMessage()); ::_exit(EXIT_FAILURE); } return waitPid(pid, status); }