LCOV - code coverage report
Current view: top level - apps/mzmqClient - mzmqClient.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 79 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 13 0

            Line data    Source code
       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.
     136              : mzmqClient * mzmqClient::m_selfClient = nullptr;
     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
     147            0 : mzmqClient::~mzmqClient() noexcept
     148              : {
     149            0 :    return;
     150            0 : }
     151              : 
     152              : inline
     153            0 : void mzmqClient::setupConfig()
     154              : {
     155            0 :    config.add("server.address", "", "server.address", argType::Required, "server", "address", false, "string", "The server's remote address. Usually localhost if using a tunnel.");
     156            0 :    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            0 :    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            0 : }
     163              : 
     164              : 
     165              : 
     166              : inline
     167            0 : void mzmqClient::loadConfig()
     168              : {
     169            0 :    m_argv0 = m_configName;
     170              : 
     171            0 :    config(m_address, "server.address");
     172            0 :    config(m_imagePort, "server.imagePort");
     173              : 
     174            0 :    config(m_shMemImNames, "server.shmimNames");
     175              : 
     176            0 :    std::cerr << "m_imagePort = " << m_imagePort << "\n";
     177              : 
     178            0 : }
     179              : 
     180              : 
     181              : #include <sys/syscall.h>
     182              : 
     183              : inline
     184            0 : int mzmqClient::appStartup()
     185              : {
     186            0 :    if(setSigSegvHandler() < 0)
     187              :    {
     188            0 :       log<software_error>({__FILE__, __LINE__});
     189            0 :       return -1;
     190              :    }
     191              : 
     192            0 :    for(size_t n=0; n < m_shMemImNames.size(); ++n)
     193              :    {
     194            0 :       shMemImName(m_shMemImNames[n]);
     195              :    }
     196              : 
     197            0 :    for(size_t n=0; n < m_imageThreads.size(); ++n)
     198              :    {
     199            0 :       if( imageThreadStart(n) > 0)
     200              :       {
     201            0 :          log<software_critical>({__FILE__, __LINE__, "Starting image thread " + m_imageThreads[n].m_imageName});
     202            0 :          return -1;
     203              :       }
     204              :    }
     205              : 
     206            0 :    return 0;
     207              : 
     208              : }
     209              : 
     210              : 
     211              : 
     212              : inline
     213            0 : int mzmqClient::appLogic()
     214              : {
     215              :    //first do a join check to see if other threads have exited.
     216              : 
     217            0 :    for(size_t n=0; n < m_imageThreads.size(); ++n)
     218              :    {
     219            0 :       if(pthread_tryjoin_np(m_imageThreads[n].m_thread->native_handle(),0) == 0)
     220              :       {
     221            0 :          log<software_error>({__FILE__, __LINE__, "image thread " + m_imageThreads[n].m_imageName + " has exited"});
     222              : 
     223            0 :          return -1;
     224              :       }
     225              :    }
     226              : 
     227              : 
     228            0 :    return 0;
     229              : 
     230              : }
     231              : 
     232              : inline
     233            0 : int mzmqClient::appShutdown()
     234              : {
     235            0 :    m_timeToDie = true;
     236              : 
     237            0 :    for(size_t n=0; n < m_imageThreads.size(); ++n)
     238              :    {
     239            0 :       imageThreadKill(n);
     240              :    }
     241              : 
     242            0 :    for(size_t n=0; n < m_imageThreads.size(); ++n)
     243              :    {
     244            0 :       if( m_imageThreads[n].m_thread->joinable())
     245              :       {
     246            0 :          m_imageThreads[n].m_thread->join();
     247              :       }
     248              :    }
     249              : 
     250            0 :    return 0;
     251              : }
     252              : 
     253              : inline
     254            0 : int mzmqClient::setSigSegvHandler()
     255              : {
     256              :    struct sigaction act;
     257              :    sigset_t set;
     258              : 
     259            0 :    act.sa_sigaction = &mzmqClient::_handlerSigSegv;
     260            0 :    act.sa_flags = SA_SIGINFO;
     261            0 :    sigemptyset(&set);
     262            0 :    act.sa_mask = set;
     263              : 
     264            0 :    errno = 0;
     265            0 :    if( sigaction(SIGSEGV, &act, 0) < 0 )
     266              :    {
     267            0 :       std::string logss = "Setting handler for SIGSEGV failed. Errno says: ";
     268            0 :       logss += strerror(errno);
     269              : 
     270            0 :       log<software_error>({__FILE__, __LINE__, errno, 0, logss});
     271              : 
     272            0 :       return -1;
     273            0 :    }
     274              : 
     275            0 :    errno = 0;
     276            0 :    if( sigaction(SIGBUS, &act, 0) < 0 )
     277              :    {
     278            0 :       std::string logss = "Setting handler for SIGBUS failed. Errno says: ";
     279            0 :       logss += strerror(errno);
     280              : 
     281            0 :       log<software_error>({__FILE__, __LINE__, errno, 0,logss});
     282              : 
     283            0 :       return -1;
     284            0 :    }
     285              : 
     286            0 :    log<text_log>("Installed SIGSEGV/SIGBUS signal handler.", logPrio::LOG_DEBUG);
     287              : 
     288            0 :    return 0;
     289              : }
     290              : 
     291              : inline
     292            0 : void mzmqClient::_handlerSigSegv( int signum,
     293              :                                     siginfo_t *siginf,
     294              :                                     void *ucont
     295              :                                   )
     296              : {
     297            0 :    m_selfClient->handlerSigSegv(signum, siginf, ucont);
     298            0 : }
     299              : 
     300              : inline
     301            0 : 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            0 :    m_restart = true;
     311              : 
     312            0 :    return;
     313              : }
     314              : 
     315              : inline
     316            0 : void mzmqClient::reportInfo( const std::string & msg )
     317              : {
     318            0 :    log<text_log>(msg, logPrio::LOG_INFO);
     319            0 : }
     320              : 
     321              : inline
     322            0 : void mzmqClient::reportNotice( const std::string & msg )
     323              : {
     324            0 :    log<text_log>(msg, logPrio::LOG_NOTICE);
     325            0 : }
     326              : 
     327              : inline
     328            0 : void mzmqClient::reportWarning( const std::string & msg )
     329              : {
     330            0 :    log<text_log>(msg, logPrio::LOG_WARNING);
     331            0 : }
     332              : 
     333              : inline
     334            0 : void mzmqClient::reportError( const std::string & msg,
     335              :                               const std::string & file,
     336              :                               int line
     337              :                             )
     338              : {
     339            0 :    log<software_error>({file.c_str(), (uint32_t) line, msg});
     340            0 : }
     341              : 
     342              : 
     343              : 
     344              : }//namespace app
     345              : } //namespace MagAOX
     346              : #endif
        

Generated by: LCOV version 2.0-1