9 #include <framework/pcore/ProcHandler.h> 
   10 #include <framework/core/InputController.h> 
   11 #include <framework/logging/Logger.h> 
   12 #include <framework/core/EventProcessor.h> 
   13 #include <framework/pcore/GlobalProcHandler.h> 
   18 #include <sys/prctl.h> 
   30   static int s_processID = -1;
 
   31   static int s_numEventProcesses = 0;
 
   32   static int s_localChildrenWithErrors = 0;
 
   38   static std::vector<int> s_pidVector;
 
   39   static int* s_pids = 
nullptr;
 
   40   static int s_numpids = 0;
 
   44     bool found_gap = 
false;
 
   45     for (
int i = 0; i < s_numpids; i++) {
 
   54       if (s_pidVector.size() == s_pidVector.capacity()) {
 
   55         B2FATAL(
"PID vector at capacity. This produces a race condition, make sure ProcHandler is created early.");
 
   57       s_pidVector.push_back(pid);
 
   59     s_pids = s_pidVector.data();
 
   60     s_numpids = s_pidVector.size();
 
   67     for (
int i = 0; i < s_numpids; i++)
 
   68       if (std::abs(s_pids[i]) == std::abs(pid))
 
   72   void removePID(
int pid)
 
   74     for (
int i = 0; i < s_numpids; i++)
 
   75       if (std::abs(s_pids[i]) == std::abs(pid))
 
   80     for (
int i = 0; i < s_numpids; i++)
 
   85     for (
int i = 0; i < s_numpids; i++)
 
   91   void sigChldHandler(
int)
 
   95     while (!pidListEmpty()) {
 
   97       int pid = waitpid(-1, &status, WNOHANG);
 
  101         } 
else if (errno == ECHILD) {
 
  103           EventProcessor::writeToStdErr(
"\n Called waitpid() without any children left. This shouldn't happen and and indicates a problem.\n");
 
  111           EventProcessor::writeToStdErr(
"\nwaitpid() failed.\n");
 
  113       } 
else if (pid == 0) {
 
  124         if (WIFSIGNALED(status)) {
 
  127           termSig = WTERMSIG(status);
 
  130           if (termSig == SIGSEGV)
 
  132         } 
else if (WIFEXITED(status) and WEXITSTATUS(status) != 0) {
 
  133           EventProcessor::writeToStdErr(
"\nExecution stopped, sub-process exited with non-zero exit status. Please check other log messages for details.\n");
 
  139             s_localChildrenWithErrors++;
 
  154 bool ProcHandler::startProc(std::set<int>* processList, 
const std::string& procType, 
int id)
 
  156   EventProcessor::installSignalHandler(SIGCHLD, sigChldHandler);
 
  163     PyOS_AfterFork_Parent();
 
  164     if (m_markChildrenAsLocal)
 
  166     processList->insert(pid);
 
  168     B2INFO(
"ProcHandler: " << procType << 
" process forked. pid = " << pid);
 
  170   } 
else if (pid < 0) {
 
  171     B2FATAL(
"fork() failed: " << strerror(errno));
 
  174     EventProcessor::installSignalHandler(SIGCHLD, SIG_IGN);
 
  178     PyOS_AfterFork_Child();
 
  180     InputController::resetForChildProcess();
 
  182     prctl(PR_SET_PDEATHSIG, SIGHUP);
 
  188 ProcHandler::ProcHandler(
unsigned int nWorkerProc, 
bool markChildrenAsLocal):
 
  189   m_markChildrenAsLocal(markChildrenAsLocal),
 
  190   m_numWorkerProcesses(nWorkerProc)
 
  192   if ((
int)nWorkerProc > s_numEventProcesses)
 
  193     s_numEventProcesses = nWorkerProc;
 
  196     B2FATAL(
"Constructing ProcHandler after forking is not allowed!");
 
  199   s_pidVector.reserve(s_pidVector.size() + nWorkerProc + 2);
 
  200   s_pids = s_pidVector.data();
 
  222   if (s_processID == -1)
 
  236   return s_numEventProcesses;
 
  241   return std::set<int>(s_pidVector.begin(), s_pidVector.end());
 
  272       if (findPID(pid) == 0) {
 
  276           s_localChildrenWithErrors--;
 
static bool isWorkerProcess()
Return true if the process is of type c_Worker.
static bool isOutputProcess()
Return true if the process is of type c_Output.
static bool isInputProcess()
Return true if the process is of type c_Input.
static bool parallelProcessingUsed()
Returns true if multiple processes have been spawned, false in single-core mode.
void startOutputProcess()
There is no real output process, but marks current process as output.
static bool isWorkerProcess()
Return true if the process is a worker process.
static int EvtProcID()
Return ID of the current process.
std::set< int > m_processList
PIDs of processes controlled by this ProcHandler.
static int numEventProcesses()
Return number of worker processes (configured value, not current)
static bool isOutputProcess()
Return true if the process is an output process.
static bool isInputProcess()
Return true if the process is an input process.
static void setProcessID(int processID)
Set the process ID of this process.
unsigned int m_numWorkerProcesses
Number of worker processes controlled by this ProcHandler.
static std::set< int > globalProcessList()
Return list of all PIDs (from all ProcHandler instances).
bool waitForAllProcesses()
Wait until all forked processes handled by this ProcHandler terminate.
static bool parallelProcessingUsed()
Returns true if multiple processes have been spawned, false in single-core mode.
bool m_markChildrenAsLocal
Anormal termination of child will not stop parent, waitForAllProcesses() returns status.
bool startProc(std::set< int > *processList, const std::string &procType, int id)
Start a new process, adding its PID to processList, and setting s_processID = id.
~ProcHandler()
Destructor.
void startWorkerProcesses()
Fork and initialize worker processes.
std::set< int > processList() const
Return list of PIDs managed by this ProcHandler instance.
void startInputProcess()
Fork and initialize an input process.
static std::string getProcessName()
Get a name for this process.
Abstract base class for different kinds of events.