// -*- c++ -*- //------------------------------------------------------------------------------ // Handlers.h //------------------------------------------------------------------------------ // Copyright (c) 2000,2005 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 _Handlers_h #define _Handlers_h #include #if !defined(WIN32) # include #endif #include "assa/EventHandler.h" #include "assa/Assure.h" namespace ASSA { #if !defined(WIN32) /** @file Handlers.h A collection of various most popular signal handlers. */ #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__NetBSD__) # define ASSAIOSIG SIGIO #else # define ASSAIOSIG SIGPOLL #endif /** SIGINTHandler handles SIGINT signal. */ class SIGINTHandler : public EventHandler { public: /// constructor SIGINTHandler(); /** Receive SIGINT signal @return 0 if valid signum_ was used, -1 otherwise. */ int handle_signal (int signum_); /** Indicates whether graceful quit signal has been raised by the signal handler. @return 0 if not, 1 othewise. */ sig_atomic_t graceful_quit(); /// Reset state of the object to initial void resetState(); private: /// flag that indicates whether signal was caught. sig_atomic_t m_graceful_quit; }; inline SIGINTHandler:: SIGINTHandler () : m_graceful_quit (0) { trace_with_mask("SIGINTHandler::SIGINTHandler", SIGHAND); } inline int SIGINTHandler:: handle_signal (int signum_) { trace_with_mask("SIGINTHandler::handle_signal", SIGHAND); if (signum_ == SIGINT) { m_graceful_quit = 1; return 0; } return -1; } inline sig_atomic_t SIGINTHandler:: graceful_quit () { return m_graceful_quit; } inline void SIGINTHandler:: resetState() { trace_with_mask("SIGINTHandler::resetState", SIGHAND); m_graceful_quit = 0; } /** Class SIGUSR1Handler. Handle SIGUSR1 signal. */ class SIGUSR1Handler : public EventHandler { public: /** Constructor */ SIGUSR1Handler() : m_count(0) { trace_with_mask("SIGUSR1Handler::SIGUSR1Handler", SIGHAND); } /** Catch USR1 signal and increment count. */ int handle_signal(int signum_) { trace_with_mask("SIGUSR1Handler::handle_signal()", SIGHAND); if (signum_ == SIGUSR1) { m_count++; DL((TRACE, "signal count = %d\n", m_count)); return 0; } return -1; } /** Report count of received signals. */ sig_atomic_t received_count() const { return m_count; } /** Set received signals count back to 0. */ void resetState() { m_count = 0; } private: /// Received signals count sig_atomic_t m_count; }; /** Class SIGUSR2Handler handles SIGUSR2 signal. */ class SIGUSR2Handler : public EventHandler { public: /** Constructor */ SIGUSR2Handler() : m_count(0) { trace_with_mask("SIGUSR2Handler::SIGUSR2Handler", SIGHAND); } /** Catch USR2 signal and increment count. */ int handle_signal(int signum_) { trace_with_mask("SIGUSR2Handler::handle_signal()", SIGHAND); if (signum_ == SIGUSR2) { m_count++; DL((TRACE, "signal count = %d\n", m_count)); return 0; } return -1; } /** Report count of received signals. */ sig_atomic_t received_count() const { return m_count; } /** Set received signals count back to 0. */ void resetState() { m_count = 0; } private: /// Received signals count sig_atomic_t m_count; }; /** Class SIGCHLDHandler handles SIGCHLD signal. */ class SIGCHLDHandler : public EventHandler { public: /// Constructor SIGCHLDHandler() : m_child_exit_flag(0) { trace_with_mask("SIGCHLDHandler::SIGCHLDHandler", SIGHAND); } /** Receive CHLD signal */ int handle_signal(int signum_) { trace_with_mask("SIGCHLDHandler::handle_signal", SIGHAND); if (signum_ == SIGCHLD && wait(NULL) != -1) { m_child_exit_flag = 1; return 0; } return -1; } /** Did child exit? */ sig_atomic_t child_exited() { return m_child_exit_flag; } /** Reset child's exit state */ void resetState() { m_child_exit_flag = 0; } private: /// Child exit's state sig_atomic_t m_child_exit_flag; }; /** Class SIGALRMHandler handles SIGALRM signal. */ class SIGALRMHandler : public EventHandler { public: /// Constructor SIGALRMHandler() : m_alarm_flag(0) { trace_with_mask("SIGALRMHandler::SIGALRMHandler", SIGHAND); } /** Receive ALRM signal */ int handle_signal(int signum_) { trace_with_mask("SIGALRMHandler::handle_signal", SIGHAND); if (signum_ == SIGALRM) { m_alarm_flag = 1; // notice that we have seen alarm return 0; } return -1; } /// Has alarm gone off? sig_atomic_t alarmed () { return m_alarm_flag; } /// Reset internal state void resetState () { m_alarm_flag = 0; } private: /// Indicator whether alarm gone off yet. sig_atomic_t m_alarm_flag; }; /** Class SIGPOLLHandler handles SIGPOLL signal. SIGPOLLHandler Implementations of dummy handler to *swallow* SIGPOLL caused sometimes by select(3) being called on false socket file descriptor. NOTE: FreeBSD uses SIGIO instead. */ class SIGPOLLHandler : public EventHandler { public: /** Constructor */ SIGPOLLHandler () { trace_with_mask("SIGPOLLHandler", SIGHAND); } /** Catch and absorb SIGPOLL signal. */ int handle_signal ( int signum_ ) { trace_with_mask("SIGPOLLHandler::handle_signal", SIGHAND); return (signum_ == ASSAIOSIG) ? 0 : -1; } }; #endif // !defined(WIN32) } // end namespace ASSA #endif