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>
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) {
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++;
163 PyOS_AfterFork_Parent();
168 B2INFO(
"ProcHandler: " << procType <<
" process forked. pid = " << pid);
170 }
else if (pid < 0) {
171 B2FATAL(
"fork() failed: " << strerror(errno));
178 PyOS_AfterFork_Child();
182 prctl(PR_SET_PDEATHSIG, SIGHUP);
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 void installSignalHandler(int sig, void(*fn)(int))
Install a signal handler 'fn' for given signal.
static void writeToStdErr(const char msg[])
async-safe method to write something to STDERR.
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.
ProcHandler(unsigned int nWorkerProc, bool markChildrenAsLocal=false)
Constructor.
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.