API
mzmqClient.hpp
Go to the documentation of this file.
1 /** \file mzmqClient.hpp
2  * \brief The MagAO-X milkzmqClient wrapper
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup mzmqClient_files
7  */
8 
9 #ifndef mzmqClient_hpp
10 #define mzmqClient_hpp
11 
12 
13 //#include <ImageStreamIO/ImageStruct.h>
14 //#include <ImageStreamIO/ImageStreamIO.h>
15 
16 #include <milkzmqClient.hpp>
17 
18 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
19 #include "../../magaox_git_version.h"
20 
21 namespace MagAOX
22 {
23 namespace app
24 {
25 
26 /** \defgroup mzmqClient ImageStreamIO 0mq Stream Client
27  * \brief Reads the contents of an ImageStreamIO image stream over a zeroMQ channel
28  *
29  * <a href="../handbook/operating/software/apps/mzmqClient.html">Application Documentation</a>
30  *
31  * \ingroup apps
32  *
33  */
34 
35 /** \defgroup mzmqClient_files ImageStreamIO Stream Synchronization
36  * \ingroup mzmqClient
37  */
38 
39 /// MagAO-X application to control reading ImageStreamIO streams from a zeroMQ channel
40 /** Contents are published to a local ImageStreamIO shmem buffer.
41  *
42  * \todo handle the alternate local name option as in the base milkzmqClient
43  * \todo md docs for this.
44  *
45  * \ingroup mzmqClient
46  *
47  */
48 class mzmqClient : public MagAOXApp<>, public milkzmq::milkzmqClient
49 {
50 
51 
52 public:
53 
54  ///Default c'tor
55  mzmqClient();
56 
57  ///Destructor
58  ~mzmqClient() noexcept;
59 
60  /// Setup the configuration system (called by MagAOXApp::setup())
61  virtual void setupConfig();
62 
63  /// load the configuration system results (called by MagAOXApp::setup())
64  virtual void loadConfig();
65 
66  /// Startup functions
67  /** Sets up the INDI vars.
68  *
69  */
70  virtual int appStartup();
71 
72  /// Implementation of the FSM for the Siglent SDG
73  virtual int appLogic();
74 
75 
76  /// Do any needed shutdown tasks. Currently nothing in this app.
77  virtual int appShutdown();
78 
79 protected:
80 
81  std::vector<std::string> m_shMemImNames;
82 
83  /** \name SIGSEGV & SIGBUS signal handling
84  * These signals occur as a result of a ImageStreamIO source server resetting (e.g. changing frame sizes).
85  * When they occur a restart of the framegrabber and framewriter thread main loops is triggered.
86  *
87  * @{
88  */
89  bool m_restart {false};
90 
91  static mzmqClient * m_selfClient; ///< 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 //Set self pointer to null so app starts up uninitialized.
137 
138 inline
139 mzmqClient::mzmqClient() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
140 {
141  m_powerMgtEnabled = false;
142 
143  return;
144 }
145 
146 inline
148 {
149  return;
150 }
151 
152 inline
154 {
155  config.add("server.address", "", "server.address", argType::Required, "server", "address", false, "string", "The server's remote address. Usually localhost if using a tunnel.");
156  config.add("server.imagePort", "", "server.imagePort", argType::Required, "server", "imagePort", false, "int", "The server's port. Usually the port on localhost forwarded to the host.");
157 
158  config.add("server.shmimNames", "", "server.shmimNames", argType::Required, "server", "shmimNames", false, "string", "List of names of the remote shmim streams to get.");
159 
160 
161 
162 }
163 
164 
165 
166 inline
168 {
169  m_argv0 = m_configName;
170 
171  config(m_address, "server.address");
172  config(m_imagePort, "server.imagePort");
173 
174  config(m_shMemImNames, "server.shmimNames");
175 
176  std::cerr << "m_imagePort = " << m_imagePort << "\n";
177 
178 }
179 
180 
181 #include <sys/syscall.h>
182 
183 inline
185 {
186  if(setSigSegvHandler() < 0)
187  {
188  log<software_error>({__FILE__, __LINE__});
189  return -1;
190  }
191 
192  for(size_t n=0; n < m_shMemImNames.size(); ++n)
193  {
194  shMemImName(m_shMemImNames[n]);
195  }
196 
197  for(size_t n=0; n < m_imageThreads.size(); ++n)
198  {
199  if( imageThreadStart(n) > 0)
200  {
201  log<software_critical>({__FILE__, __LINE__, "Starting image thread " + m_imageThreads[n].m_imageName});
202  return -1;
203  }
204  }
205 
206  return 0;
207 
208 }
209 
210 
211 
212 inline
214 {
215  //first do a join check to see if other threads have exited.
216 
217  for(size_t n=0; n < m_imageThreads.size(); ++n)
218  {
219  if(pthread_tryjoin_np(m_imageThreads[n].m_thread->native_handle(),0) == 0)
220  {
221  log<software_error>({__FILE__, __LINE__, "image thread " + m_imageThreads[n].m_imageName + " has exited"});
222 
223  return -1;
224  }
225  }
226 
227 
228  return 0;
229 
230 }
231 
232 inline
234 {
235  m_timeToDie = true;
236 
237  for(size_t n=0; n < m_imageThreads.size(); ++n)
238  {
239  imageThreadKill(n);
240  }
241 
242  for(size_t n=0; n < m_imageThreads.size(); ++n)
243  {
244  if( m_imageThreads[n].m_thread->joinable())
245  {
246  m_imageThreads[n].m_thread->join();
247  }
248  }
249 
250  return 0;
251 }
252 
253 inline
255 {
256  struct sigaction act;
257  sigset_t set;
258 
259  act.sa_sigaction = &mzmqClient::_handlerSigSegv;
260  act.sa_flags = SA_SIGINFO;
261  sigemptyset(&set);
262  act.sa_mask = set;
263 
264  errno = 0;
265  if( sigaction(SIGSEGV, &act, 0) < 0 )
266  {
267  std::string logss = "Setting handler for SIGSEGV failed. Errno says: ";
268  logss += strerror(errno);
269 
270  log<software_error>({__FILE__, __LINE__, errno, 0, logss});
271 
272  return -1;
273  }
274 
275  errno = 0;
276  if( sigaction(SIGBUS, &act, 0) < 0 )
277  {
278  std::string logss = "Setting handler for SIGBUS failed. Errno says: ";
279  logss += strerror(errno);
280 
281  log<software_error>({__FILE__, __LINE__, errno, 0,logss});
282 
283  return -1;
284  }
285 
286  log<text_log>("Installed SIGSEGV/SIGBUS signal handler.", logPrio::LOG_DEBUG);
287 
288  return 0;
289 }
290 
291 inline
293  siginfo_t *siginf,
294  void *ucont
295  )
296 {
297  m_selfClient->handlerSigSegv(signum, siginf, ucont);
298 }
299 
300 inline
301 void mzmqClient::handlerSigSegv( int signum,
302  siginfo_t *siginf,
303  void *ucont
304  )
305 {
306  static_cast<void>(signum);
307  static_cast<void>(siginf);
308  static_cast<void>(ucont);
309 
310  m_restart = true;
311 
312  return;
313 }
314 
315 inline
316 void mzmqClient::reportInfo( const std::string & msg )
317 {
318  log<text_log>(msg, logPrio::LOG_INFO);
319 }
320 
321 inline
322 void mzmqClient::reportNotice( const std::string & msg )
323 {
324  log<text_log>(msg, logPrio::LOG_NOTICE);
325 }
326 
327 inline
328 void mzmqClient::reportWarning( const std::string & msg )
329 {
330  log<text_log>(msg, logPrio::LOG_WARNING);
331 }
332 
333 inline
334 void mzmqClient::reportError( const std::string & msg,
335  const std::string & file,
336  int line
337  )
338 {
339  log<software_error>({file.c_str(), (uint32_t) line, msg});
340 }
341 
342 
343 
344 }//namespace app
345 } //namespace MagAOX
346 #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 reading ImageStreamIO streams from a zeroMQ channel.
Definition: mzmqClient.hpp:49
virtual int appLogic()
Implementation of the FSM for the Siglent SDG.
Definition: mzmqClient.hpp:213
static mzmqClient * m_selfClient
Static pointer to this (set in constructor). Used for getting out of the static SIGSEGV handler.
Definition: mzmqClient.hpp:91
virtual void reportNotice(const std::string &msg)
Log status (with LOG_NOTICE level of priority).
Definition: mzmqClient.hpp:322
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
Definition: mzmqClient.hpp:233
mzmqClient()
Default c'tor.
Definition: mzmqClient.hpp:139
virtual void reportWarning(const std::string &msg)
Log a warning.
Definition: mzmqClient.hpp:328
void handlerSigSegv(int signum, siginfo_t *siginf, void *ucont)
Handles SIGSEGV and SIGBUS. Sets m_restart to true.
Definition: mzmqClient.hpp:301
virtual void reportInfo(const std::string &msg)
Log status (with LOG_INFO level of priority).
Definition: mzmqClient.hpp:316
int setSigSegvHandler()
Sets the handler for SIGSEGV and SIGBUS.
Definition: mzmqClient.hpp:254
~mzmqClient() noexcept
Destructor.
Definition: mzmqClient.hpp:147
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
Definition: mzmqClient.hpp:153
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: mzmqClient.hpp:292
virtual int appStartup()
Startup functions.
Definition: mzmqClient.hpp:184
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
Definition: mzmqClient.hpp:167
std::vector< std::string > m_shMemImNames
Definition: mzmqClient.hpp:81
virtual void reportError(const std::string &msg, const std::string &file, int line)
Log an error.
Definition: mzmqClient.hpp:334
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