From: Christian Herdtweck Date: Tue, 23 Dec 2014 17:42:23 +0000 (+0100) Subject: temp commit before leaving, started to change signal handling and use singel io_service X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=fc7ae593c47bde3994f1f1cbd40310cc901e8a25;p=pingcheck temp commit before leaving, started to change signal handling and use singel io_service --- diff --git a/src/host/pinger.h b/src/host/pinger.h index 203e585..7355637 100644 --- a/src/host/pinger.h +++ b/src/host/pinger.h @@ -28,6 +28,13 @@ #include #include #include +#include + +//----------------------------------------------------------------------------- +// IoServiceItem +//----------------------------------------------------------------------------- + +typedef boost::shared_ptr IoServiceItem; //----------------------------------------------------------------------------- // Pinger diff --git a/src/host/pingrotate.cpp b/src/host/pingrotate.cpp index 9ad8987..598fb5c 100644 --- a/src/host/pingrotate.cpp +++ b/src/host/pingrotate.cpp @@ -48,7 +48,7 @@ using boost::shared_ptr; * host. The protocols will be used in the order they are in the list. */ PingRotate::PingRotate( - io_service &io_serv, + IoServiceItem io_serv, const string &network_interface, const string &destination_address, const uint16_t destination_port, diff --git a/src/host/pingrotate.h b/src/host/pingrotate.h index e5a68c9..078b91b 100644 --- a/src/host/pingrotate.h +++ b/src/host/pingrotate.h @@ -46,7 +46,7 @@ class PingRotate { public: PingRotate( - boost::asio::io_service &io_serv, + IoServiceItem io_serv, const std::string &network_interface, const std::string &destination_address, const uint16_t destination_port, @@ -83,7 +83,7 @@ private: // /// The IO service object, which has the loop event - boost::asio::io_service &IoService; + IoServiceItem IoService; /// The network interface name std::string NetworkInterfaceName; /// The list of IPs which are aliases to the host DNS diff --git a/src/host/pingscheduler.cpp b/src/host/pingscheduler.cpp index bced749..ca07c15 100644 --- a/src/host/pingscheduler.cpp +++ b/src/host/pingscheduler.cpp @@ -61,6 +61,7 @@ using I2n::Logger::GlobalLogger; * @param first_delay Delay in seconds from start_pinging_thread to first ping attempt */ PingScheduler::PingScheduler( + IoServiceItem io_service, const string &network_interface, const string &destination_address, const uint16_t destination_port, @@ -75,9 +76,9 @@ PingScheduler::PingScheduler( const int first_delay ) : - IoService(), - NextPingTimer( IoService ), - NextAddressTimer( IoService ), + IoService( io_service ), + NextPingTimer( io_service ), + NextAddressTimer( io_service ), TimeSentLastPing( microsec_clock::universal_time() ), PingIntervalInSec( ping_interval_in_sec ), AddressResolveIntervalInSec( ping_interval_in_sec ), diff --git a/src/main.cpp b/src/main.cpp index 0416b24..778c839 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,7 @@ on this file might be covered by the GNU General Public License. #include #include #include +#include #include #include @@ -43,13 +44,14 @@ on this file might be covered by the GNU General Public License. using namespace std; -using boost::asio::io_service; using boost::shared_ptr; +using boost:posix::time_duration; using I2n::Logger::GlobalLogger; // a map from interval (in seconds) to delay (in seconds) typedef std::pair IntervalCountPair; typedef std::map DelayMap; +typedef shared_ptr IoServiceItem; //----------------------------------------------------------------------------- // Declarations @@ -185,6 +187,7 @@ DelayMap calc_pinger_delays(const HostList &hosts) } void init_pingers( + IoServiceItem io_service, const ConfigurationItem &configuration, const LinkStatusItem &status_notifier, PingSchedulerList *scheduler_list @@ -226,6 +229,7 @@ void init_pingers( PingSchedulerItem scheduler( new PingScheduler( + io_service, network_interface, destination_address, destination_port, @@ -254,8 +258,7 @@ void start_pingers( bool started = scheduler->start_pinging_thread(); if ( !started ) { - GlobalLogger.error() << "Error: could not start pinger." - << endl; + GlobalLogger.error() << "Could not start pinger." << endl; } } } @@ -289,7 +292,7 @@ void block_all_signals() sigset_t all_signals; int result = sigfillset( &all_signals ); if ( result == -1 ) { - GlobalLogger.error() << "Error: sigfillset failed." << endl; + GlobalLogger.error() << "Sigfillset failed." << endl; } result = sigprocmask( SIG_SETMASK, &all_signals, NULL ); @@ -311,7 +314,7 @@ void handle_signals( const int default_log_level ) sigset_t all_signals; int result = sigfillset( &all_signals ); if ( result == -1 ) { - GlobalLogger.error() << "Error: sigfillset failed." << endl; + GlobalLogger.error() << "Sigfillset failed." << endl; } // Synchronously process signals @@ -347,6 +350,72 @@ void handle_signals( const int default_log_level ) } } +// data required for signal handling (SIGINT, SIGTERM, ... ) +struct signal_data_struct +{ + sig_atomic_t signaled_flag; + void (*old_handler_int )(int); + void (*old_handler_term)(int); + void (*old_handler_usr1)(int); + void (*old_handler_usr2)(int); + boost::asio::deadline_timer check_timer; + time_duration check_interval; + IoServiceItem io_service; +}; +signal_data_struct signal_data; + +void signal_handler(int param) +{ + GlobalLogger.info() << "signal handler called with param " << param << endl; + signal_data.signaled_flag = param; +} + +void signal_checker( const boost::system::error_code &error ) +{ + GlobalLogger.debug() << "signal checker called with arg " << error; + if ( error ) + if ( !signal_data.signaled_flag) + { // schedule another timer + signal_data.check_timer.expires_from_now( signal_data.check_interval ); + signal_data.check_timer.async_wait( signal_checker ); + return; + } + else + { + // so there has been a signal --> stop + // actually, see handle_signals for what to do + GlobalLogger.error() << "not implemented yet, see handle_signals for what to do!" + << endl; + signal_data.io_service->stop() + } +} + +bool install_signal_handler( IoServiceItem io_service, + const time_duration &check_interval ) +{ + signal_data.signaled_flag = 0; + + // install own signal handlers + signal_data.old_handler_int = signal(SIGINT, signal_handler); + signal_data.old_handler_term = signal(SIGTERM, signal_handler); + signal_data.old_handler_usr1 = signal(SIGUSR1, signal_handler); + signal_data.old_handler_usr2 = signal(SIGUSR2, signal_handler); + if ( signal_data.old_handler_int == SIG_ERR || + signal_data.old_handler_term == SIG_ERR || + signal_data.old_handler_usr1 == SIG_ERR || + signal_data.old_handler_usr2 == SIG_ERR ) + throw runtime_error( "Failed to install signal handler: " + strerror(errno) ); + + // add timer to io_service that calls signal_checker + signal_data.check_interval = check_interval; + signal_data.io_service = io_service; + signal_data.check_timer( io_service ); + signal_data.check_timer.expires_from_now( check_interval ); + + // start timer + signal_data.check_timer.async_wait( signal_checker ); +} + int main( int argc, const char *argv[] ) { // Block all signals before creating any threads @@ -360,57 +429,78 @@ int main( int argc, const char *argv[] ) try { ConfigurationItem configuration = get_configuration( argc, argv ); - if ( configuration.get() != NULL ) + if ( configuration.get() == NULL ) { - int log_level = configuration->get_log_level(); - I2n::Logger::set_log_level( log_level ); //lint !e534 - GlobalLogger.info() << "Set LogLevel to " << I2n::Logger::get_log_level_string() << endl; + GlobalLogger.error() << "no configuration!"; + return 1; + } - set_log_output( configuration ); - GlobalLogger.notice() << "started"; + int log_level = configuration->get_log_level(); + I2n::Logger::set_log_level( log_level ); //lint !e534 + GlobalLogger.info() << "Set LogLevel to " << I2n::Logger::get_log_level_string() << endl; - bool daemon_mode = configuration->get_daemon(); - if ( daemon_mode ) - { - I2n::Daemon::daemonize(); - } + set_log_output( configuration ); + GlobalLogger.notice() << "started"; - LinkStatusItem status_notifier = get_status_notifier( configuration ); + bool daemon_mode = configuration->get_daemon(); + if ( daemon_mode ) + { + I2n::Daemon::daemonize(); + } - init_pingers( configuration, status_notifier, &scheduler_list ); + LinkStatusItem status_notifier = get_status_notifier( configuration ); - start_pingers( scheduler_list ); + IoServiceItem io_service( new boost::asio::io_service() ); + + init_pingers( io_service, configuration, status_notifier, &scheduler_list ); + + //start_pingers( scheduler_list ); + + install_signal_handler( io_service ); - // React to signals (main thread will sleep) - handle_signals( log_level ); - } } catch ( const std::exception &ex ) { - GlobalLogger.error() << "Error: uncaught exception. " << ex.what() << endl; + GlobalLogger.error() << "Uncaught exception. " << ex.what() << endl; ret_code = 1; } catch (...) { - GlobalLogger.error() << "Error: caught unknown exception!" << endl; + GlobalLogger.error() << "Caught unknown exception!" << endl; ret_code = 2; } + // call boost::asio main event loop, ignoring exceptions + while ( true ) + { + try + { + io_service->run(); + } + catch ( const std::exception &ex ) + { + GlobalLogger.error() << "Caught exception, will continue. " << ex.what() << endl; + } + catch (...) { + GlobalLogger.error() << "Caught unknown exception, will continue!" << endl; + } + } + // clean up try { GlobalLogger.info() << "Cleaning up" << endl; stop_pingers( scheduler_list ); - GlobalLogger.notice() << "exiting"; } catch ( const std::exception &ex ) { - GlobalLogger.error() << "Error: uncaught exception while cleaning up " << ex.what() << endl; + GlobalLogger.error() << "Uncaught exception while cleaning up: " << ex.what() << endl; ret_code += 4; } catch (...) { - GlobalLogger.error() << "Error: caught unknown exception while cleaning up!" << endl; + GlobalLogger.error() << "Caught unknown exception while cleaning up!" << endl; ret_code += 8; } + GlobalLogger.notice() << "Pingcheck done" << endl; return ret_code; }