Diana Software
QProcessStatus.cc
Go to the documentation of this file.
1 #include "QProcessStatus.hh"
2 
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <signal.h>
6 #include <string>
7 #include <iostream>
8 
9 #include "QError.hh"
10 
11 //________________________________________________________________________
13 {
14  static QProcessStatus instance;
15  return instance;
16 }
17 
18 
19 //________________________________________________________________________
21  QNamed(""),
22  QId(::getpid()),
23  fState(QIdle_s),
24  fPreviousState(QIdle_s),
25  fTrgCtrl(false),
26  fInformEnabled(false),
27  kMaxQueued(4),
28  fError("")
29 {
30  fStatusQueue.clear();
31  fSigMap.clear();
32  return;
33 }
34 
35 
36 //_____________________________________________________________________________
37 void QProcessStatus::Disable(int signalId)
38 {
39  fSigMap.erase(signalId);
40  signal(signalId,SIG_DFL);
41 }
42 
43 
44 //_____________________________________________________________________________
45 bool QProcessStatus::Ignore(int signalId)
46 {
47  if(signalId == SIGSEGV || signalId == SIGFPE)
48  return false;
49 
50  fSigMap[signalId] = QIgnore_s;
51  signal(signalId,SIG_IGN);
52  return true;
53 }
54 
55 
56 //_____________________________________________________________________________
57 void QProcessStatus::Associate(int signalId, ProcessStatus_t pStatus)
58 {
59  signal(signalId, SigHandler);
60  if( (signalId == SIGFPE) || (signalId == SIGSEGV) )
61  fSigMap[signalId] = QError_s;
62  else
63  fSigMap[signalId] = pStatus;
64 }
65 
66 
67 //_____________________________________________________________________________
68 void QProcessStatus::HandleSignal(int signalId)
69 {
70  // reset error message
71  SetError("");
72 
73  // get process status
74  std::map<int,ProcessStatus_t>::const_iterator sigMapIt;
75  if((sigMapIt = fSigMap.find(signalId)) == fSigMap.end())
76  {
77  std::cerr << "received unhandled signal " << signalId << std::endl;
78  return;
79  }
80  const ProcessStatus_t newStatus = sigMapIt->second;
81  const ProcessStatus_t lastStatus = GetLastStatus();
82 
83 
84  // QError_s
85  if(QError_s == newStatus)
86  {
87  // exit immediately if this is not the first detected error
88  if(std::find(fStatusQueue.begin(),fStatusQueue.end(),
89  QError_s) != fStatusQueue.end())
90  {
91  std::cerr << "Unhandled critical Error: ";
92  if(SIGSEGV == signalId)
93  std::cerr << "Segmentation violation. ";
94  if(SIGFPE == signalId)
95  std::cerr << "Floating point exception. ";
96  std::cerr << "Exit forced" << std::endl;
97  exit(1);
98  }
99 
100  if(signalId == SIGSEGV)
101  SetError("Segmentation Fault detected");
102  else if(signalId == SIGFPE)
103  SetError("Floating Point Exception detected");
104 
106  return;
107  }
108 
109 
110  // QExiting_s
111  else if(QExiting_s == newStatus)
112  {
114  return;
115  }
116 
117 
118  // QStopped_s
119  else if(QStopped_s == newStatus)
120  {
121  if (QRunning_s == lastStatus
122  || QPaused_s == lastStatus
123  || QWaiting_s == lastStatus )
125  else
126  SetError("Invalid state. Cannot STOP");
127 
128  return;
129  }
130 
131  // QWaiting_s
132  else if(QWaiting_s == newStatus)
133  {
134  if (QReady_s == lastStatus
135  || QPaused_s == lastStatus )
137  else
138  SetError("Invalid state. Cannot START (in 'wait mode')");
139 
140  return;
141  }
142 
143  // QRunning_s
144  else if(QRunning_s == newStatus)
145  {
146  if (QReady_s == lastStatus
147  || QPaused_s == lastStatus
148  || QWaiting_s == lastStatus )
150  else
151  SetError("Invalid state. Cannot START");
152 
153  return;
154  }
155 
156 
157  // QIdle_s
158  else if(QIdle_s == newStatus)
159  {
161  return;
162  }
163 
164 
165  // QAskStatus_s
166  else if(QAskStatus_s == newStatus)
167  {
168  InformServer();
169  return;
170  }
171 
172 
173  // QTriggerOff_s
174  else if(QTriggerOff_s == newStatus && TrgCtrlEnabled())
175  {
176  if (QRunning_s == lastStatus
177  || QPaused_s == lastStatus
178  || QWaiting_s == lastStatus )
180  else
181  SetError("Cannot disable trigger if process is neither "
182  "running nor ready");
183 
184  return;
185  }
186 
187 
188  // QTriggerOn_s
189  else if(QTriggerOn_s == newStatus && TrgCtrlEnabled())
190  {
191  if (QRunning_s == lastStatus
192  || QPaused_s == lastStatus
193  || QWaiting_s == lastStatus )
195  else
196  SetError("Cannot re-enable trigger if process is neither "
197  "running nor ready");
198  }
199 
200  // should never get here
201  else
202  {
204  SetError("Unexpected signal or process status");
205  std::cerr << "Error in signal handler: cannot handle signal "
206  << signalId << std::endl;
207  }
208  return;
209 }
210 
211 
212 //_____________________________________________________________________________
214 {
215  if(!fInformEnabled)
216  return;
218  //QApolloMessenger& msg = QApolloMessenger::GetInstance();
219  //err = msg.SendStatus(fState);
220  if(err != QERR_SUCCESS)
221  std::cout << err << std::endl;
222  return;
223 }
224 
225 
226 //_____________________________________________________________________________
228 {
230  fState = state;
231  fStatusQueue.clear();
232  InformServer();
233  std::cout << "set state called: old "
235  << " new "
236  << fState.AsString()
237  << std::endl;
238  return;
239 }
240 
241 
242 //________________________________________________________________________
244 {
245  // cannot notify non-existent status
246  if(fStatusQueue.empty())
247  return;
248 
250  fState = fStatusQueue.front();
251  fStatusQueue.pop_front();
252  InformServer();
253  return;
254 }
255 
256 
257 //________________________________________________________________________
259 {
260  // in case trigger on/off status is added to queue, also last state
261  // is added
263  fStatusQueue.push_back(state);
264  if(QTriggerOn_s == state
265  || QTriggerOff_s == state)
266  {
267  fStatusQueue.push_back(last);
268  }
269  if(fStatusQueue.size() > kMaxQueued)
270  {
271  std::cerr << "Warning: maximum process status queue size exceeded"
272  << std::endl;
273  }
274 }
275 
276 
277 //________________________________________________________________________
279 {
280  if(fStatusQueue.empty())
281  return fState;
282  return fStatusQueue.back();
283 }
284 
285 
286 //_____________________________________________________________________________
287 void SigHandler(int signalId)
288 {
289  std::cout << "QProcessStatus: signal " << signalId << " ("
290  << strsignal(signalId) << ") detected" << std::endl;
292  status.HandleSignal(signalId);
293 }
err
Definition: CheckOF.C:114
@ QIdle_s
@ QPaused_s
@ QStopped_s
@ QExiting_s
@ QAskStatus_s
@ QError_s
@ QWaiting_s
@ QRunning_s
@ QIgnore_s
@ QReady_s
@ QTriggerOff_s
@ QTriggerOn_s
@ QERR_SUCCESS
Definition: QError.hh:27
void SigHandler(int signalId)
signal handler function
wrapper for ProcessStatus_ enum
std::string AsString() const
convert to string
error class with error type and description
Definition: QError.hh:115
base class for anything having an id
Definition: QId.hh:13
base class for anything that has a name
Definition: QNamed.hh:14
process status and signal handler
std::map< int, ProcessStatus_t > fSigMap
void Notify()
acknowledge oldest process status contained in staus queue
ProcessStatus_t fState
current process status
bool TrgCtrlEnabled() const
check wether trigger control signals are enabled
friend void SigHandler(int)
signal handler function
void SetError(const std::string &errMsg)
set error string
const size_t kMaxQueued
ProcessStatus_t GetLastStatus() const
get last status that have been added to status queue. If queue is empty current process status is ret...
static QProcessStatus & GetInstance()
get singleton Instance
void AddToQueue(ProcessStatus_t state)
add state to process status queue.
void InformServer()
inform MsgServer about current process status
bool Ignore(int signalId)
ignore signal
std::deque< ProcessStatus_t > fStatusQueue
void HandleSignal(int signalId)
this method is called each time a registered signal is caught. It updates the status queue and inform...
void Associate(int signalId, ProcessStatus_t pStatus)
associate a signal to a given process status
void SetState(ProcessStatus_t state)
change current process status bypassing status queue vector
ProcessStatus_t fPreviousState
previous process status
void Disable(int signalId)
disable handling of a signal (use defauls system handler)