API
mzmqServer.hpp
Go to the documentation of this file.
1 /** \file mzmqServer.hpp
2  * \brief The MagAO-X milkzmqServer wrapper
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup mzmqServer_files
7  */
8 
9 #ifndef mzmqServer_hpp
10 #define mzmqServer_hpp
11 
12 
13 //#include <ImageStruct.h>
14 //#include <ImageStreamIO.h>
15 
16 #include <milkzmqServer.hpp>
17 
18 //#include <mx/timeUtils.hpp>
19 
20 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
21 #include "../../magaox_git_version.h"
22 
23 
24 
25 namespace MagAOX
26 {
27 namespace app
28 {
29 
30 /** \defgroup mzmqServer ImageStreamIO Stream Server
31  * \brief Writes the contents of an ImageStreamIO image stream over a zeroMQ channel
32  *
33  * <a href="../handbook/operating/software/apps/mzmqServer.html">Application Documentation</a>
34  *
35  * \ingroup apps
36  *
37  */
38 
39 /** \defgroup mzmqServer_files ImageStreamIO Stream Synchronization
40  * \ingroup mzmqServer
41  */
42 
43 /// MagAO-X application to control writing ImageStreamIO streams to a zeroMQ channel
44 /** \todo document this better
45  * \todo implement thread-kills for shutdown. Maybe switch to USR1, with library wide empty handler, so it isn't logged.
46  * \ingroup mzmqServer
47  *
48  */
49 class mzmqServer : public MagAOXApp<>, public milkzmq::milkzmqServer
50 {
51 
52 
53 public:
54 
55  ///Default c'tor
56  mzmqServer();
57 
58  ///Destructor
59  ~mzmqServer() noexcept;
60 
61  /// Setup the configuration system (called by MagAOXApp::setup())
62  virtual void setupConfig();
63 
64  /// load the configuration system results (called by MagAOXApp::setup())
65  virtual void loadConfig();
66 
67  /// Startup functions
68  /** Sets up the INDI vars.
69  *
70  */
71  virtual int appStartup();
72 
73  /// Implementation of the FSM for the Siglent SDG
74  virtual int appLogic();
75 
76 
77  /// Do any needed shutdown tasks. Currently nothing in this app.
78  virtual int appShutdown();
79 
80 protected:
81 
82  bool m_compress {false};
83  std::vector<std::string> m_shMemImNames;
84 
85  /** \name SIGSEGV & SIGBUS signal handling
86  * These signals occur as a result of a ImageStreamIO source server resetting (e.g. changing frame sizes).
87  * When they occur a restart of the framegrabber and framewriter thread main loops is triggered.
88  *
89  * @{
90  */
91  static mzmqServer * m_selfWriter; ///< Static pointer to this (set in constructor). Used for getting out of the static SIGSEGV handler.
92 
93  ///Sets the handler for SIGSEGV and SIGBUS
94  /** These are caused by ImageStreamIO server resets.
95  */
96  int setSigSegvHandler();
97 
98  ///The handler called when SIGSEGV or SIGBUS is received, which will be due to ImageStreamIO server resets. Just a wrapper for handlerSigSegv.
99  static void _handlerSigSegv( int signum,
100  siginfo_t *siginf,
101  void *ucont
102  );
103 
104  ///Handles SIGSEGV and SIGBUS. Sets m_restart to true.
105  void handlerSigSegv( int signum,
106  siginfo_t *siginf,
107  void *ucont
108  );
109  ///@}
110 
111 
112  /** \name milkzmq Status and Error Handling
113  * Implementation of status updates, warnings, and errors from milkzmq using logs.
114  *
115  * @{
116  */
117 
118  /// Log status (with LOG_INFO level of priority).
119  virtual void reportInfo( const std::string & msg /**< [in] the status message */);
120 
121  /// Log status (with LOG_NOTICE level of priority).
122  virtual void reportNotice( const std::string & msg /**< [in] the status message */);
123 
124  /// Log a warning.
125  virtual void reportWarning( const std::string & msg /**< [in] the warning message */);
126 
127  /// Log an error.
128  virtual void reportError( const std::string & msg, ///< [in] the error message
129  const std::string & file, ///< [in] the name of the file where the error occurred
130  int line ///< [in] the line number of the error
131  );
132  ///@}
133 
134 };
135 
136 //Set self pointer to null so app starts up uninitialized.
138 
139 inline
140 mzmqServer::mzmqServer() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
141 {
142  m_powerMgtEnabled = false;
143 
144  return;
145 }
146 
147 inline
149 {
150  return;
151 }
152 
153 inline
155 {
156  config.add("server.imagePort", "", "server.imagePort", argType::Required, "server", "imagePort", false, "int", "");
157 
158  config.add("server.shmimNames", "", "server.shmimNames", argType::Required, "server", "shmimNames", false, "string", "");
159 
160  config.add("server.usecSleep", "", "server.usecSleep", argType::Required, "server", "usecSleep", false, "int", "");
161 
162  config.add("server.fpsTgt", "", "server.fpsTgt", argType::Required, "server", "fpsTgt", false, "float", "");
163 
164  config.add("server.fpsGain", "", "server.fpsGain", argType::Required, "server", "fpsGain", false, "float", "");
165 
166  config.add("server.compress", "", "server.compress", argType::Required, "server", "compress", false, "bool", "Flag to turn on compression for INT16 and UINT16.");
167 
168 }
169 
170 
171 
172 inline
174 {
175  m_argv0 = m_configName;
176 
177  config(m_imagePort, "server.imagePort");
178 
179  config(m_shMemImNames, "server.shmimNames");
180  config(m_usecSleep, "server.usecSleep");
181  config(m_fpsTgt, "server.fpsTgt");
182 
183  config(m_fpsGain, "server.fpsGain");
184 
185  config(m_compress, "server.compress");
186 
187 
188 }
189 
190 
191 #include <sys/syscall.h>
192 
193 inline
195 {
196 
197  //Now set up the framegrabber and writer threads.
198  // - need SIGSEGV and SIGBUS handling for ImageStreamIO restarts
199  // - initialize the semaphore
200  // - start the threads
201 
202  if(setSigSegvHandler() < 0)
203  {
204  log<software_error>({__FILE__, __LINE__});
205  return -1;
206  }
207 
208  if(m_compress) defaultCompression();
209 
210  for(size_t n=0; n < m_shMemImNames.size(); ++n)
211  {
212  shMemImName(m_shMemImNames[n]);
213  }
214 
215  if(serverThreadStart() < 0)
216  {
217  log<software_critical>({__FILE__, __LINE__});
218  return -1;
219  }
220 
221  for(size_t n=0; n < m_imageThreads.size(); ++n)
222  {
223  if( imageThreadStart(n) > 0)
224  {
225  log<software_critical>({__FILE__, __LINE__, "Starting image thread " + m_imageThreads[n].m_imageName});
226  return -1;
227  }
228  }
229 
230 
231  std::cerr << "Main Thread: " << syscall(SYS_gettid) << "\n";
232 
233  return 0;
234 
235 }
236 
237 
238 
239 inline
241 {
242  //first do a join check to see if other threads have exited.
243 
244  if(pthread_tryjoin_np(m_serverThread.native_handle(),0) == 0)
245  {
246  log<software_error>({__FILE__, __LINE__, "server thread has exited"});
247 
248  return -1;
249  }
250 
251  for(size_t n=0; n < m_imageThreads.size(); ++n)
252  {
253  if(pthread_tryjoin_np(m_imageThreads[n].m_thread->native_handle(),0) == 0)
254  {
255  log<software_error>({__FILE__, __LINE__, "image thread " + m_imageThreads[n].m_imageName + " has exited"});
256 
257  return -1;
258  }
259  }
260 
261 
262  return 0;
263 
264 }
265 
266 inline
268 {
269  m_timeToDie = true;
270 
271  for(size_t n=0; n < m_imageThreads.size(); ++n)
272  {
273  imageThreadKill(n);
274  }
275 
276  for(size_t n=0; n < m_imageThreads.size(); ++n)
277  {
278  if( m_imageThreads[n].m_thread->joinable())
279  {
280  m_imageThreads[n].m_thread->join();
281  }
282  }
283 
284  return 0;
285 }
286 
287 inline
289 {
290  struct sigaction act;
291  sigset_t set;
292 
293  act.sa_sigaction = &mzmqServer::_handlerSigSegv;
294  act.sa_flags = SA_SIGINFO;
295  sigemptyset(&set);
296  act.sa_mask = set;
297 
298  errno = 0;
299  if( sigaction(SIGSEGV, &act, 0) < 0 )
300  {
301  std::string logss = "Setting handler for SIGSEGV failed. Errno says: ";
302  logss += strerror(errno);
303 
304  log<software_error>({__FILE__, __LINE__, errno, 0, logss});
305 
306  return -1;
307  }
308 
309  errno = 0;
310  if( sigaction(SIGBUS, &act, 0) < 0 )
311  {
312  std::string logss = "Setting handler for SIGBUS failed. Errno says: ";
313  logss += strerror(errno);
314 
315  log<software_error>({__FILE__, __LINE__, errno, 0,logss});
316 
317  return -1;
318  }
319 
320  log<text_log>("Installed SIGSEGV/SIGBUS signal handler.", logPrio::LOG_DEBUG);
321 
322  return 0;
323 }
324 
325 inline
327  siginfo_t *siginf,
328  void *ucont
329  )
330 {
331  m_selfWriter->handlerSigSegv(signum, siginf, ucont);
332 }
333 
334 inline
335 void mzmqServer::handlerSigSegv( int signum,
336  siginfo_t *siginf,
337  void *ucont
338  )
339 {
340  static_cast<void>(signum);
341  static_cast<void>(siginf);
342  static_cast<void>(ucont);
343 
344  milkzmqServer::m_restart = true;
345 
346  return;
347 }
348 
349 inline
350 void mzmqServer::reportInfo( const std::string & msg )
351 {
352  log<text_log>(msg, logPrio::LOG_INFO);
353 }
354 
355 inline
356 void mzmqServer::reportNotice( const std::string & msg )
357 {
358  log<text_log>(msg, logPrio::LOG_NOTICE);
359 }
360 
361 inline
362 void mzmqServer::reportWarning( const std::string & msg )
363 {
364  log<text_log>(msg, logPrio::LOG_WARNING);
365 }
366 
367 inline
368 void mzmqServer::reportError( const std::string & msg,
369  const std::string & file,
370  int line
371  )
372 {
373  log<software_error>({file.c_str(), (uint32_t) line, msg});
374 }
375 
376 
377 
378 }//namespace app
379 } //namespace MagAOX
380 #endif
The base-class for MagAO-X applications.
Definition: MagAOXApp.hpp:73
std::string m_configName
The name of the configuration file (minus .conf).
Definition: MagAOXApp.hpp:83
MagAO-X application to control writing ImageStreamIO streams to a zeroMQ channel.
Definition: mzmqServer.hpp:50
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
Definition: mzmqServer.hpp:154
int setSigSegvHandler()
Sets the handler for SIGSEGV and SIGBUS.
Definition: mzmqServer.hpp:288
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
Definition: mzmqServer.hpp:173
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
Definition: mzmqServer.hpp:267
virtual int appStartup()
Startup functions.
Definition: mzmqServer.hpp:194
static void _handlerSigSegv(int signum, siginfo_t *siginf, void *ucont)
The handler called when SIGSEGV or SIGBUS is received, which will be due to ImageStreamIO server rese...
Definition: mzmqServer.hpp:326
virtual void reportError(const std::string &msg, const std::string &file, int line)
Log an error.
Definition: mzmqServer.hpp:368
virtual int appLogic()
Implementation of the FSM for the Siglent SDG.
Definition: mzmqServer.hpp:240
void handlerSigSegv(int signum, siginfo_t *siginf, void *ucont)
Handles SIGSEGV and SIGBUS. Sets m_restart to true.
Definition: mzmqServer.hpp:335
virtual void reportNotice(const std::string &msg)
Log status (with LOG_NOTICE level of priority).
Definition: mzmqServer.hpp:356
mzmqServer()
Default c'tor.
Definition: mzmqServer.hpp:140
virtual void reportInfo(const std::string &msg)
Log status (with LOG_INFO level of priority).
Definition: mzmqServer.hpp:350
static mzmqServer * m_selfWriter
Static pointer to this (set in constructor). Used for getting out of the static SIGSEGV handler.
Definition: mzmqServer.hpp:91
std::vector< std::string > m_shMemImNames
Definition: mzmqServer.hpp:83
~mzmqServer() noexcept
Destructor.
Definition: mzmqServer.hpp:148
virtual void reportWarning(const std::string &msg)
Log a warning.
Definition: mzmqServer.hpp:362
std::ostream & cerr()
std::stringstream msg
Definition: dm.hpp:24
constexpr static logPrioT LOG_DEBUG
Used for debugging.
Definition: logPriority.hpp:52
constexpr static logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
Definition: logPriority.hpp:49
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
Definition: logPriority.hpp:43
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.
Definition: logPriority.hpp:46