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);
   }
}
Esempio n. 2
0
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);
}