9 #include <framework/pcore/GlobalProcHandler.h>
10 #include <framework/core/InputController.h>
11 #include <framework/logging/Logger.h>
12 #include <framework/core/EventProcessor.h>
15 #include <sys/prctl.h>
31 ProcType GlobalProcHandler::s_procType = ProcType::c_Init;
32 int GlobalProcHandler::s_processID = -1;
33 int GlobalProcHandler::s_numEventProcesses = 0;
35 std::vector<int> GlobalProcHandler::s_pidVector;
36 std::map<int, ProcType> GlobalProcHandler::s_startedPIDs;
38 void GlobalProcHandler::childSignalHandler(
int)
40 while (!GlobalProcHandler::pidListEmpty()) {
42 int pid = waitpid(-1, &status, WNOHANG);
46 }
else if (errno == ECHILD) {
48 EventProcessor::writeToStdErr(
"\n Called waitpid() without any children left. This shouldn't happen and and indicates a problem.\n");
51 GlobalProcHandler::clearPIDs();
55 EventProcessor::writeToStdErr(
"\nwaitpid() failed.\n");
57 }
else if (pid == 0) {
64 if (not GlobalProcHandler::findPID(pid)) {
70 if (WIFSIGNALED(status) or (WIFEXITED(status) and WEXITSTATUS(status) != 0)) {
71 EventProcessor::writeToStdErr(
"\nSub-process exited with non-zero exit status. Please check other log messages for details.\n");
75 GlobalProcHandler::removePID(pid);
81 void GlobalProcHandler::addPID(
int newPID)
84 for (
int& pid : s_pidVector) {
91 B2FATAL(
"PID vector at capacity. This produces a race condition, make sure GlobalProcHandler is created early.");
94 bool GlobalProcHandler::findPID(
int pid)
96 return std::find(s_pidVector.begin(), s_pidVector.end(), pid) != s_pidVector.end();
99 void GlobalProcHandler::removePID(
int oldPID)
101 for (
int& pid : s_pidVector) {
109 void GlobalProcHandler::clearPIDs()
111 std::fill(s_pidVector.begin(), s_pidVector.end(), 0);
114 bool GlobalProcHandler::pidListEmpty()
116 for (
const int& pid : s_pidVector) {
124 void GlobalProcHandler::initialize(
unsigned int nWorkerProc)
126 B2ASSERT(
"Constructing GlobalProcHandler after forking is not allowed!", pidListEmpty());
128 s_numEventProcesses = nWorkerProc;
131 s_pidVector.resize(s_pidVector.size() + nWorkerProc + 3, 0);
134 bool GlobalProcHandler::startProxyProcess()
136 return startProc(ProcType::c_Proxy, 30000);
139 bool GlobalProcHandler::startInputProcess()
141 return startProc(ProcType::c_Input, 10000);
144 bool GlobalProcHandler::startWorkerProcesses(
unsigned int numProcesses)
146 for (
unsigned int i = 0; i < numProcesses; i++) {
147 if (startProc(ProcType::c_Worker, 0)) {
154 bool GlobalProcHandler::startOutputProcess(
bool local)
157 s_procType = ProcType::c_Output;
160 return (startProc(ProcType::c_Output, 20000));
164 bool GlobalProcHandler::startMonitoringProcess()
166 s_procType = ProcType::c_Monitor;
170 bool GlobalProcHandler::parallelProcessingUsed()
172 return s_processID != -1;
175 bool GlobalProcHandler::isProcess(
ProcType procType)
177 return (procType == s_procType);
180 bool GlobalProcHandler::startProc(
ProcType procType,
int id)
182 EventProcessor::installSignalHandler(SIGCHLD, childSignalHandler);
190 s_startedPIDs[pid] = procType;
192 }
else if (pid < 0) {
193 B2FATAL(
"fork() failed: " << strerror(errno));
197 EventProcessor::installSignalHandler(SIGCHLD, SIG_IGN);
199 s_procType = procType;
202 s_processID = getpid();
207 PyOS_AfterFork_Child();
209 InputController::resetForChildProcess();
211 prctl(PR_SET_PDEATHSIG, SIGHUP);
217 std::string GlobalProcHandler::getProcessName()
219 if (isProcess(ProcType::c_Worker))
221 if (isProcess(ProcType::c_Input))
223 if (isProcess(ProcType::c_Output))
225 if (isProcess(ProcType::c_Init))
227 if (isProcess(ProcType::c_Monitor))
234 int GlobalProcHandler::EvtProcID()
239 void GlobalProcHandler::killAllProcesses()
241 for (
int& pid : s_pidVector) {
243 if (kill(pid, SIGKILL) >= 0) {
244 B2ERROR(
"hard killed process " << pid);
246 B2DEBUG(100,
"no process " << pid <<
" found, already gone?");
253 const std::vector<int>& GlobalProcHandler::getPIDList()
260 const auto procTypeIt = s_startedPIDs.find(pid);
261 if (procTypeIt == s_startedPIDs.end()) {
262 B2FATAL(
"Asking for a non-existing PID");
264 return procTypeIt->second;
267 int GlobalProcHandler::numEventProcesses()
269 return s_numEventProcesses;
272 bool GlobalProcHandler::isOutputProcess()
274 return isProcess(ProcType::c_Output);
277 bool GlobalProcHandler::isWorkerProcess()
279 return isProcess(ProcType::c_Worker);
282 bool GlobalProcHandler::isInputProcess()
284 return isProcess(ProcType::c_Input);
287 void GlobalProcHandler::waitForAllProcesses()
290 if (pidListEmpty()) {
294 std::this_thread::sleep_for(std::chrono::milliseconds(1));
ProcType
Type of the process used for storing and mapping the child processes in the process handler.
Abstract base class for different kinds of events.