LCOV - code coverage report
Current view: top level - eventdispatcher - signal_child.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 1 100.0 %
Date: 2021-09-19 09:06:58 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2021  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/eventdispatcher
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : #pragma once
      20             : 
      21             : /** \file
      22             :  * \brief Handle the SIGCHLD specifically.
      23             :  *
      24             :  * This class is used to capture the SIGCHLD signal from the OS and call
      25             :  * a corresponding callback function.
      26             :  *
      27             :  * Whenever you want to knwow whether a child you created died, you can
      28             :  * use this class. Get the instance (it's a singleton) and then use the
      29             :  * add_listener().
      30             :  *
      31             :  * Once you get called with a child that exited or was signaled, that
      32             :  * listener is automatically removed from the list of listeners (since
      33             :  * the child is gone, there is really no need for that listener).
      34             :  */
      35             : 
      36             : // self
      37             : //
      38             : #include    "eventdispatcher/signal.h"
      39             : 
      40             : 
      41             : // cppthread lib
      42             : //
      43             : #include    <cppthread/mutex.h>
      44             : 
      45             : 
      46             : // C++ lib
      47             : //
      48             : #include    <functional>
      49             : #include    <list>
      50             : 
      51             : 
      52             : // C lib
      53             : //
      54             : #include    <sys/resource.h>
      55             : #include    <sys/signalfd.h>
      56             : #include    <sys/wait.h>
      57             : 
      58             : 
      59             : 
      60             : namespace ed
      61             : {
      62             : 
      63             : 
      64             : 
      65             : typedef std::uint32_t           flag_t;
      66             : 
      67             : constexpr flag_t const          SIGNAL_CHILD_FLAG_RUNNING       = 0x0001;
      68             : constexpr flag_t const          SIGNAL_CHILD_FLAG_EXITED        = 0x0002;
      69             : constexpr flag_t const          SIGNAL_CHILD_FLAG_SIGNALED      = 0x0004;
      70             : constexpr flag_t const          SIGNAL_CHILD_FLAG_STOPPED       = 0x0008;
      71             : constexpr flag_t const          SIGNAL_CHILD_FLAG_CONTINUED     = 0x0010;
      72             : 
      73             : 
      74             : class child_status
      75             : {
      76             : public:
      77             :                         child_status(siginfo_t const & info);
      78             : 
      79             :     pid_t               child_pid() const;
      80             :     uid_t               child_uid() const;
      81             :     bool                is_running() const;
      82             :     bool                is_exited() const;
      83             :     bool                is_signaled() const;
      84             :     bool                is_core_dumped() const;
      85             :     bool                is_stopped() const;
      86             :     bool                is_continued() const;
      87             :     flag_t              status_mask() const;
      88             : 
      89             :     int                 exit_code() const;
      90             :     int                 terminate_signal() const;
      91             :     int                 stop_signal() const;
      92             : 
      93             : private:
      94             :     siginfo_t           f_info = siginfo_t();
      95             : };
      96             : 
      97             : 
      98             : class signal_child
      99             :     : public signal
     100             : {
     101             : public:
     102             :     typedef std::shared_ptr<signal_child>     pointer_t;
     103             :     typedef std::function<void(child_status status)> func_t;
     104             : 
     105             :     virtual                     ~signal_child() override;
     106             : 
     107             :     static pointer_t            get_instance();
     108             : 
     109             :     // signal implementation
     110             :     //
     111             :     virtual void                process_signal() override;
     112             :     virtual void                connection_added() override;
     113             :     virtual void                connection_removed() override;
     114             : 
     115             :     void                        add_listener(
     116             :                                       pid_t child
     117             :                                     , func_t callback
     118             :                                     , flag_t mask = SIGNAL_CHILD_FLAG_EXITED | SIGNAL_CHILD_FLAG_SIGNALED);
     119             :     void                        remove_listener(pid_t child);
     120             : 
     121             : private:
     122          44 :     struct callback_t
     123             :     {
     124             :         typedef std::list<callback_t>     list_t;
     125             : 
     126             :         pid_t           f_child = 0;
     127             :         func_t          f_callback = 0;
     128             :         flag_t          f_flags = 0;
     129             :     };
     130             : 
     131             :     explicit                    signal_child();
     132             : 
     133             :     void                        add_connection();
     134             :     void                        remove_connection();
     135             : 
     136             :     callback_t::list_t          f_listeners = callback_t::list_t();
     137             :     cppthread::mutex            f_mutex = cppthread::mutex();
     138             :     std::uint32_t               f_count = 0;
     139             :     bool                        f_adding_to_communicator = false;
     140             :     bool                        f_removing_to_communicator = false;
     141             : };
     142             : 
     143             : 
     144             : 
     145             : } // namespace ed
     146             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13