Belle II Software development
ProcessController.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include "daq/slc/readout/ProcessController.h"
9
10#include "daq/slc/readout/ProcessListener.h"
11#include "daq/slc/readout/LogListener.h"
12#include "daq/slc/runcontrol/RCHandlerException.h"
13
14#include "daq/slc/system/Executor.h"
15#include "daq/slc/system/PThread.h"
16#include "daq/slc/system/LogFile.h"
17
18#include "daq/slc/base/StringUtil.h"
19#include <daq/slc/system/LockGuard.h>
20
21#include <cstdio>
22#include <unistd.h>
23
24
25using namespace Belle2;
26
27bool ProcessController::init(const std::string& parname, int nodeid)
28{
29 m_name = StringUtil::tolower(m_callback->getNode().getName());
30 m_parname = parname;
31 LogFile::open(m_name + "_" + m_parname);
32 if (!m_info.open(m_name + "_" + m_parname, nodeid, true)) {
33 return false;
34 }
35 m_callback->add(new NSMVHandlerInt(m_parname + ".pid", true, false, 0), false, false);
36 return true;
37}
38
39void ProcessController::clear()
40{
41 m_info.clear();
42}
43
44bool ProcessController::waitReady(int timeout)
45{
46 if (!m_info.waitReady(timeout)) {
47 return false;
48 }
49 return true;
50}
51
52bool ProcessController::load(int timeout)
53{
54 m_info.clear();
55 m_process.cancel();
56 m_process.kill(SIGABRT);
57 if (pipe(m_iopipe) < 0) {
58 perror("pipe");
59 return false;
60 }
61 m_process = Process(new ProcessSubmitter(this, m_iopipe));
62 m_th_log = PThread(new LogListener(this, m_iopipe));
63 m_th_process = PThread(new ProcessListener(this));
64 //close(iopipe[1]);
65 if (timeout > 0) {
66 if (!m_info.waitReady(timeout)) {
67 throw (RCHandlerException("Failed to boot " + m_parname));
68 }
69 }
70 m_callback->set(m_parname + ".pid", m_process.get_id());
71 return true;
72}
73
74bool ProcessController::start(int expno, int runno)
75{
76 GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
77 m_info.setExpNumber(expno);
78 m_info.setRunNumber(runno);
79 m_info.setSubNumber(0);
80 /*
81 if (m_info.getState() != RunInfoBuffer::RUNNING) {
82 throw (RCHandlerException(m_parname + " is not running"));
83 }
84 */
85 return true;
86}
87
88bool ProcessController::stop()
89{
90 GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
91 m_info.setExpNumber(0);
92 m_info.setRunNumber(0);
93 m_info.setSubNumber(0);
94 m_info.setInputCount(0);
95 m_info.setInputNBytes(0);
96 m_info.setOutputCount(0);
97 m_info.setOutputNBytes(0);
98 return true;
99}
100
101bool ProcessController::pause()
102{
103 GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
104 if (m_info.isRunning()) {
105 m_info.setState(RunInfoBuffer::PAUSED);
106 } else {
107 LogFile::warning("Process is not running. Pause request was ignored.");
108 }
109 return true;
110}
111
112bool ProcessController::resume()
113{
114 GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
115 if (m_info.isPaused()) {
116 m_info.setState(RunInfoBuffer::RUNNING);
117 } else {
118 LogFile::warning("Process is not paused. Resume request was ignored.");
119 }
120 return true;
121}
122
123bool ProcessController::abort(unsigned int timeout)
124{
125 m_info.clear();
126 m_process.kill(SIGINT);
127
128 bool sigintWasSuccessful = false;
129 for (unsigned int timer = 0; timer < timeout; ++timer) {
130 if (not m_process.isAlive()) {
131 sigintWasSuccessful = true;
132 break;
133 } else {
134 usleep(1000000);
135 }
136 }
137
138 if (sigintWasSuccessful) {
139 LogFile::debug("Process successfully killed with SIGINT.");
140 } else {
141 LogFile::warning("Process could not be killed with SIGINT, sending SIGABRT.");
142 m_process.kill(SIGABRT);
143 }
144
145 if (m_callback != NULL)
146 m_callback->set(m_parname + ".pid", -1);
147 m_process.wait();
148 m_th_log.cancel();
149 m_th_process.cancel();
150 close(m_iopipe[1]);
151 close(m_iopipe[0]);
152 return true;
153}
154
155void ProcessSubmitter::run()
156{
157 //close(1);
158 dup2(m_iopipe[1], 1);
159 //close(2);
160 dup2(m_iopipe[1], 2);
161 close(m_iopipe[0]);
162 Executor executor;
163 if (m_con->getExecutable().size() == 0) {
164 m_con->setExecutable("basf2");
165 }
166 executor.setExecutable(m_con->getExecutable());
167 for (size_t i = 0; i < m_con->m_arg_v.size(); i++) {
168 executor.addArg(m_con->m_arg_v[i]);
169 }
170 executor.execute();
171}
172
173void ProcessController::addArgument(const char* format, ...)
174{
175 va_list ap;
176 static char ss[1024];
177 va_start(ap, format);
178 vsprintf(ss, format, ap);
179 va_end(ap);
180 m_arg_v.push_back(ss);
181}
Lock Guard for a Mutex instance.
Definition: LockGuard.h:47
Abstract base class for different kinds of events.