Belle II Software  release-08-01-10
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 
25 using namespace Belle2;
26 
27 bool 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 
39 void ProcessController::clear()
40 {
41  m_info.clear();
42 }
43 
44 bool ProcessController::waitReady(int timeout)
45 {
46  if (!m_info.waitReady(timeout)) {
47  return false;
48  }
49  return true;
50 }
51 
52 bool 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  return false;
69  }
70  }
71  m_callback->set(m_parname + ".pid", m_process.get_id());
72  return true;
73 }
74 
75 bool ProcessController::start(int expno, int runno)
76 {
77  GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
78  m_info.setExpNumber(expno);
79  m_info.setRunNumber(runno);
80  m_info.setSubNumber(0);
81  /*
82  if (m_info.getState() != RunInfoBuffer::RUNNING) {
83  throw (RCHandlerException(m_parname + " is not running"));
84  }
85  */
86  return true;
87 }
88 
89 bool ProcessController::stop()
90 {
91  GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
92  m_info.setExpNumber(0);
93  m_info.setRunNumber(0);
94  m_info.setSubNumber(0);
95  m_info.setInputCount(0);
96  m_info.setInputNBytes(0);
97  m_info.setOutputCount(0);
98  m_info.setOutputNBytes(0);
99  return true;
100 }
101 
102 bool ProcessController::pause()
103 {
104  GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
105  if (m_info.isRunning()) {
106  m_info.setState(RunInfoBuffer::PAUSED);
107  } else {
108  LogFile::warning("Process is not running. Pause request was ignored.");
109  }
110  return true;
111 }
112 
113 bool ProcessController::resume()
114 {
115  GenericLockGuard<RunInfoBuffer> lockGuard(m_info);
116  if (m_info.isPaused()) {
117  m_info.setState(RunInfoBuffer::RUNNING);
118  } else {
119  LogFile::warning("Process is not paused. Resume request was ignored.");
120  }
121  return true;
122 }
123 
124 bool ProcessController::abort(unsigned int timeout)
125 {
126  m_info.clear();
127  m_process.kill(SIGINT);
128 
129  bool sigintWasSuccessful = false;
130  for (unsigned int timer = 0; timer < timeout; ++timer) {
131  if (not m_process.isAlive()) {
132  sigintWasSuccessful = true;
133  break;
134  } else {
135  usleep(1000000);
136  }
137  }
138 
139  if (sigintWasSuccessful) {
140  LogFile::debug("Process successfully killed with SIGINT.");
141  } else {
142  LogFile::warning("Process could not be killed with SIGINT, sending SIGABRT.");
143  m_process.kill(SIGABRT);
144  }
145 
146  if (m_callback != NULL)
147  m_callback->set(m_parname + ".pid", -1);
148  m_process.wait();
149  m_th_log.cancel();
150  m_th_process.cancel();
151  close(m_iopipe[1]);
152  close(m_iopipe[0]);
153  return true;
154 }
155 
156 void ProcessSubmitter::run()
157 {
158  //close(1);
159  dup2(m_iopipe[1], 1);
160  //close(2);
161  dup2(m_iopipe[1], 2);
162  close(m_iopipe[0]);
163  Executor executor;
164  if (m_con->getExecutable().size() == 0) {
165  m_con->setExecutable("basf2");
166  }
167  executor.setExecutable(m_con->getExecutable());
168  for (size_t i = 0; i < m_con->m_arg_v.size(); i++) {
169  executor.addArg(m_con->m_arg_v[i]);
170  }
171  executor.execute();
172 }
173 
174 void ProcessController::addArgument(const char* format, ...)
175 {
176  va_list ap;
177  static char ss[1024];
178  va_start(ap, format);
179  vsprintf(ss, format, ap);
180  va_end(ap);
181  m_arg_v.push_back(ss);
182 }
Lock Guard for a Mutex instance.
Definition: LockGuard.h:47
Abstract base class for different kinds of events.