// -*- c++ -*- //------------------------------------------------------------------------------ // SigAction.h //------------------------------------------------------------------------------ // Copyright (c) 1997 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #ifndef _SigAction_h #define _SigAction_h // System includes // #include #include #include "assa/Assure.h" #include "assa/SigSet.h" // some convenient typedefs // extern "C" { typedef struct sigaction SIGACTION; typedef void (*C_SIG_HANDLER)( int ); } namespace ASSA { #if !defined(WIN32) /** @file SigAction.h SigAction is a C++ wrapper around sigaction structure Class SigAction implements a C++ wrapper around struct sigaction. It class also provides a range of all possible operation that can be performed on it, including sigaction(2) system call. struct sigaction is defined as:
   struct sigaction {
       void      (*sa_handler) ();
       sigset_t  sa_mask;
       int       sa_flags;
       void      (*sa_sigaction) (int, siginfo_t*, void*);
   };
It is used to set all the details of what your process should do when a signal arrives. It encapsulates the action to be taken on receipt of a particular signal. The most important member is sa_handler, which takes a pointer to a function. This function will be invoked whenever the process gets a particular POSIX.1 signal. Some of the member function of SigAction class take a parameter of type C_SIG_HANDLER. It can be one of: - "C" signal handling function (sa_handler above):\n void sig_handler (int signum) - SIG_ERR - SIG DFL takes default signal action when caught - SIG_IGN ignores signal (for those that can be ignored) The sa_mask mask for the signal action specifies a set of signals to be blocked while the signal handler is active. On the entry into the signal handler, that set of signals is added to a set of signals already being blocked from delivery when the signal is delivered to the process. In addition, the signal that caused the handler to be executed will also be blocked (SIGSTOP and SIGKILL cannot be blocked - this is enforced by the underlying OS). Flags sa_flags in the set of flags ORed that allows to modify the delivery of the signal. POSIX.1 spec. defines only SA_NOCLDSTOP flag. All other flags are system-dependent. Consult your local sigaction(2) man page for details. Because SigAction is a wrapper around sigaction(2), after sig_handler returns (and before anything else), the OS will reinstall current disposition for the signal. To reset signal's disposition to SIG_DFL, SUN Solaris OS uses flag SA_RESETHAND, and Linux OS uses SA_ONESHOT. */ class SigAction { public: /** Default constructor creates SigAction object with null-action. */ SigAction(); /** Construct a SigAction object with "C" signal handler function. This constructor doesn't install any actions - it is merely a shell for actiono to be installed for any signal(s). Thus, you can reuse the same object for number of differen signals. @param handler_ "C" signal handler function to call. @param sig_mask_ Set of signals to block while handler_ is active. @param flags_ Controls behavior of signal handler (OS-specific: see Available Options: section of documentation). */ SigAction (C_SIG_HANDLER handler_, SigSet* sig_mask_ = 0, int flags_ = 0); /** Construct a SigAction with "C" signal handler function and change program's disposition for signum_ immediately.

First argument is the "C" function. It cannot be a non-static C++ class member function. This function pretty much simulates C-like approach the the signal handling. For C++ member function approach, see SigHandler & Co. @param handler_ "C" signal handler function to call. @param signum_ Signal which disposition is to change. @param sig_mask_ Set of signals to block while handler_ is active. @param flags_ Controls behavior of signal handler (OS-specific: see Available Options: section of documentation). */ SigAction (C_SIG_HANDLER handler_, int signum_, SigSet* sig_mask_ = 0, int flags_ = 0); /** Register this object as current disposition for signal signum_, and store old disposition in oaction_, if not NULL. This function installs C_SIG_HANDLER this object represents, thus simulating C-like approach to signal handling. @param signum_ Signal which disposition to install. @param oaction_ Placeholder for the old disposition. @return 0 on success, -1 on error, with errno indicating the error. */ int register_action (int signum_, SigAction* oaction_ = 0); /** Change object's disposition to oaction_, and install it as current disposition for the signal signum_. @param signum_ Signal which disposition to restore. @param oaction_ Disposition to restore. @return 0 on success, -1 on error, with errno indicating the error. */ int restore_action (int signum_, SigAction& oaction_); /** Retrieve current disposition for the signal signum_ into this object. @param signum_ Signal number @return 0 on success, -1 on error, with errno indicating the error. */ int retrieve_action (int signum_); /** Set sigaction structure to sa_ @param sa_ New value for internal struct sigaction. */ void action (SIGACTION * sa_); /** Retrieve current sigaction. @return Pointer to an internal struct sigaction. */ SIGACTION * action (); /** Set signal flags to new_flags_. @param new_flags_ New flags for this action. */ void flags (int new_flags_); /** Retrieve current flags. @return Value of current flags for this action. */ int flags (); /** Set new signal mask mask_set_. */ void mask (SigSet & mask_set_); /** Retrieve current signal mask. */ SigSet mask (); /** Set new signal handler to function pointer sha_. */ void handler (C_SIG_HANDLER sha_); /** Retrieve current signal handler function. */ C_SIG_HANDLER handler (); /** Conversion operator that converts SigAction to a pointer to the internal struct sigaction data member for direct use with C-library functions. */ operator SIGACTION *(); private: /// sigaction structure itself SIGACTION m_sa; }; //------------------------------------------------------------------------- //------------------------Inline functions--------------------------------- //------------------------------------------------------------------------- inline SigAction:: SigAction () { trace_with_mask("SigAction::SigAction", SIGACT); m_sa.sa_flags = 0; sigemptyset(&m_sa.sa_mask); *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) 0; } inline SigAction:: SigAction (C_SIG_HANDLER handler_, SigSet* sig_mask_, int flags_) { trace_with_mask("SigAction::SigAction(,,)", SIGACT); m_sa.sa_flags = flags_; if (sig_mask_ == NULL) { sigemptyset(&m_sa.sa_mask); } else { /*--- here, suppose to do bitwise structure assignment, but does it really do so? = *sig_mask_ = *(sig_mask_.operator *()) = *(SigSet *tmp = &sig_mask_.m_sa) ???? ---*/ m_sa.sa_mask = **sig_mask_; } *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) handler_; } inline SigAction:: SigAction (C_SIG_HANDLER handler_, int signum_, SigSet* sig_mask_, int flags_) { trace_with_mask("SigAction::SigAction(,,,)", SIGACT); m_sa.sa_flags = flags_; if (sig_mask_ == NULL) { sigemptyset(&m_sa.sa_mask); } else { /*--- same problem as above... ---*/ m_sa.sa_mask = **sig_mask_; } *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) handler_; /*--- installing disposition... ---*/ sigaction (signum_, &m_sa, 0); } inline void SigAction:: action (SIGACTION* sa_) { trace_with_mask("SigAction::action", SIGACT); m_sa = *sa_; } inline SIGACTION * SigAction:: action () { trace_with_mask("SigAction::action", SIGACT); return &m_sa; } inline void SigAction:: flags (int new_flags_) { trace_with_mask("void SigAction::flags()", SIGACT); m_sa.sa_flags = new_flags_; } inline int SigAction:: flags () { trace_with_mask("int SigAction::flags()", SIGACT); return m_sa.sa_flags; } inline void SigAction:: mask (SigSet & mask_set_) { trace_with_mask("void SigAction::mask()", SIGACT); m_sa.sa_mask = *mask_set_; } inline SigSet SigAction:: mask () { trace_with_mask("SigSet SigAction::mask()", SIGACT); SigSet tmpset(&m_sa.sa_mask); return tmpset; } inline void SigAction:: handler (C_SIG_HANDLER sha_) { trace_with_mask("void SigAction::handler()", SIGACT); *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) sha_; } inline C_SIG_HANDLER SigAction:: handler () { trace_with_mask("C_SIG_HANDLER SigAction::handler()", SIGACT); return (C_SIG_HANDLER) m_sa.sa_handler; } inline SigAction::operator SIGACTION * () { trace_with_mask("SigAction::operator SIGACTION * ()", SIGACT); return &m_sa; } inline int SigAction:: register_action (int signum_, SigAction* oaction_) { trace_with_mask("SigAction::register_action()", SIGACT); /*--- place here recursive mutex lock to guard ... ---*/ struct sigaction *osa = oaction_ == 0 ? 0 : oaction_->action(); return sigaction(signum_, &m_sa, osa); } inline int SigAction:: restore_action (int signum_, SigAction& oaction_) { trace_with_mask("SigAction::restore_action()", SIGACT); m_sa = *oaction_.action(); return sigaction(signum_, &m_sa, 0); } inline int SigAction:: retrieve_action (int signum_) { trace_with_mask("SigAction::retrieve_action()", SIGACT); return sigaction(signum_, 0, &m_sa); } #endif // !defined(WIN32) } // end namespace ASSA #endif /* _SigAction_h */