From: Christian Herdtweck Date: Tue, 30 Dec 2014 17:14:06 +0000 (+0100) Subject: new signal handling in main; removed all thread-related vars, use same IoServiceItem... X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=365036bee44340b24832bc4f989cbd1d97b1628b;p=pingcheck new signal handling in main; removed all thread-related vars, use same IoServiceItem instead --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d9f1253..a1d5cd6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,9 +3,9 @@ include(FindPkgConfig) # package: required boost libraries set(Boost_USE_STATIC_LIBS OFF) -set(Boost_USE_MULTITHREADED ON) +set(Boost_USE_MULTITHREADED OFF) set(Boost_USE_STATIC_RUNTIME OFF) -find_package(Boost 1.44 COMPONENTS filesystem program_options system thread REQUIRED) +find_package(Boost 1.44 COMPONENTS filesystem program_options system REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) diff --git a/src/host/pingerfactory.cpp b/src/host/pingerfactory.cpp index 24f2bcd..7df5039 100644 --- a/src/host/pingerfactory.cpp +++ b/src/host/pingerfactory.cpp @@ -33,7 +33,6 @@ using namespace std; using boost::shared_ptr; -using boost::asio::io_service; using boost::asio::ip::icmp; using boost::asio::ip::tcp_raw_protocol; using boost::system::system_error; @@ -67,7 +66,7 @@ PingerFactory::~PingerFactory() */ PingerItem PingerFactory::createPinger( const PingProtocol protocol, - io_service &io_serv, + const IoServiceItem io_serv, const string &network_interface, const int ping_reply_timeout ) @@ -126,7 +125,7 @@ PingerItem PingerFactory::createPinger( */ PingRotateItem PingerFactory::createPinger( const PingProtocolList &protocol_list, - io_service &io_serv, + const IoServiceItem io_serv, const string &network_interface, const string &destination_address, const uint16_t destination_port, diff --git a/src/host/pingerfactory.h b/src/host/pingerfactory.h index 5e6e918..118ec24 100644 --- a/src/host/pingerfactory.h +++ b/src/host/pingerfactory.h @@ -39,14 +39,14 @@ class PingerFactory public: static PingerItem createPinger( const PingProtocol protocol, - boost::asio::io_service &io_serv, + const IoServiceItem io_serv, const std::string &network_interface, const int ping_reply_timeout ); static PingRotateItem createPinger( const PingProtocolList &protocol_list, - boost::asio::io_service &io_serv, + const IoServiceItem io_serv, const std::string &network_interface, const std::string &destination_address, const uint16_t destination_port, diff --git a/src/host/pingrotate.cpp b/src/host/pingrotate.cpp index 598fb5c..19e2a43 100644 --- a/src/host/pingrotate.cpp +++ b/src/host/pingrotate.cpp @@ -27,7 +27,6 @@ #include "host/pingerfactory.h" using namespace std; -using boost::asio::io_service; using boost::function; using boost::shared_ptr; @@ -48,7 +47,7 @@ using boost::shared_ptr; * host. The protocols will be used in the order they are in the list. */ PingRotate::PingRotate( - IoServiceItem io_serv, + const 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 078b91b..e287e16 100644 --- a/src/host/pingrotate.h +++ b/src/host/pingrotate.h @@ -46,7 +46,7 @@ class PingRotate { public: PingRotate( - IoServiceItem io_serv, + const IoServiceItem io_serv, const std::string &network_interface, const std::string &destination_address, const uint16_t destination_port, diff --git a/src/host/pingscheduler.cpp b/src/host/pingscheduler.cpp index ca07c15..e7b9e3e 100644 --- a/src/host/pingscheduler.cpp +++ b/src/host/pingscheduler.cpp @@ -39,7 +39,6 @@ using boost::date_time::time_resolution_traits_adapted64_impl; using boost::posix_time::microsec_clock; using boost::posix_time::ptime; using boost::posix_time::seconds; -using boost::thread; using boost::shared_ptr; using I2n::Logger::GlobalLogger; @@ -58,10 +57,10 @@ using I2n::Logger::GlobalLogger; * @param ping_fail_percentage_limit Maximum amount of pings that can fail. * @param nameserver Server to resolve the addresses. * @param link_analyzer The object to monitor the link status. - * @param first_delay Delay in seconds from start_pinging_thread to first ping attempt + * @param first_delay Delay in seconds from start_pinging to first ping attempt */ PingScheduler::PingScheduler( - IoServiceItem io_service, + const IoServiceItem io_service, const string &network_interface, const string &destination_address, const uint16_t destination_port, @@ -76,9 +75,8 @@ PingScheduler::PingScheduler( const int first_delay ) : - IoService( io_service ), - NextPingTimer( io_service ), - NextAddressTimer( io_service ), + NextPingTimer( *io_service ), + NextAddressTimer( *io_service ), TimeSentLastPing( microsec_clock::universal_time() ), PingIntervalInSec( ping_interval_in_sec ), AddressResolveIntervalInSec( ping_interval_in_sec ), @@ -87,8 +85,7 @@ PingScheduler::PingScheduler( AddressResolutionAttempts( 0 ), MaxAddressResolutionAttempts( max_address_resolution_attempts ), EverHadAnyIP( false ), - Ping(), - Thread() + Ping() { BOOST_ASSERT( !network_interface.empty() ); BOOST_ASSERT( !destination_address.empty() ); @@ -99,7 +96,7 @@ PingScheduler::PingScheduler( Ping = PingerFactory::createPinger( ping_protocol_list, - IoService, + io_service, network_interface, destination_address, destination_port, @@ -116,44 +113,13 @@ PingScheduler::~PingScheduler() { } -/** - * @brief Starts the pinging thread and returns immediately. - */ -bool PingScheduler::start_pinging_thread() -{ - Thread = thread( &PingScheduler::start_pinging, this ); //lint !e1793 - - return true; -} - -/** - * @brief Waits for the pinging thread to finish. - */ -void PingScheduler::wait_pinging_thread() -{ - BOOST_ASSERT( Thread.joinable() ); - - Thread.join(); -} - -/** - * @brief Stops pinging the host. Request the thread to finish, which makes the - * any blocking wait (join) on this object to return. - */ -void PingScheduler::stop_pinging_thread() -{ - stop_pinging(); -} - void PingScheduler::stop_pinging() { - // This is thread safe - IoService.stop(); } /** - * @brief Start into infinite loop of calls to resolve_and_ping, using an - * IoService which is started here and can be stopped through stop_pinging[_thread] + * @brief Start into infinite loop of calls to resolve_and_ping + * IoService which is started here and can be stopped through stop_pinging */ void PingScheduler::start_pinging() { @@ -167,10 +133,6 @@ void PingScheduler::start_pinging() } else resolve_and_ping(); - - // event processing loop, it is a blocking call! - IoService.run(); //lint !e534 - GlobalLogger.info() << "Ping thread was stopped."; } diff --git a/src/host/pingscheduler.h b/src/host/pingscheduler.h index 8192a9e..1cdeaec 100644 --- a/src/host/pingscheduler.h +++ b/src/host/pingscheduler.h @@ -27,7 +27,6 @@ on this file might be covered by the GNU General Public License. #include #include -#include #include "link/linkstatus.h" #include "host/hoststatus.h" @@ -49,6 +48,7 @@ class PingScheduler { public: PingScheduler( + const IoServiceItem io_service, const std::string &network_interface, const std::string &destination_address, const uint16_t destination_port, @@ -64,18 +64,14 @@ public: ); ~PingScheduler(); - bool start_pinging_thread(); - void wait_pinging_thread(); - void stop_pinging_thread(); + void start_pinging(); + void stop_pinging(); private: // // Methods // - void start_pinging(); - void stop_pinging(); - void resolve_and_ping(); bool resolve_address(); void force_address_resolution(); @@ -89,8 +85,6 @@ private: // Attributes // - /// Service object, which has the event loop - boost::asio::io_service IoService; /// Timer to trigger the next ping boost::asio::deadline_timer NextPingTimer; /// Timer to trigger the next attempt to resolve addresses @@ -113,8 +107,6 @@ private: bool EverHadAnyIP; /// Internal boost pinger object PingRotateItem Ping; - /// Thread object - boost::thread Thread; }; //----------------------------------------------------------------------------- diff --git a/src/icmp/icmppinger.cpp b/src/icmp/icmppinger.cpp index c1076a7..fa76a05 100644 --- a/src/icmp/icmppinger.cpp +++ b/src/icmp/icmppinger.cpp @@ -51,17 +51,16 @@ static const std::size_t SOCKET_BUFFER_SIZE = 65536; // 64kB * @param echo_reply_timeout_in_sec The amount of time to wait for a reply. */ IcmpPinger::IcmpPinger( - io_service &io_serv, + const IoServiceItem io_serv, const icmp::socket::protocol_type &protocol, const string &source_network_interface, const int echo_reply_timeout_in_sec ) : - IoService( io_serv ), DestinationEndpoint(), Protocol( protocol ), - Socket( IoService, Protocol ), + Socket( *io_serv, Protocol ), NetInterface( source_network_interface, Socket ), - IcmpPacketReceiveTimer( IoService ), + IcmpPacketReceiveTimer( *io_serv ), Identifier( 0 ), SequenceNumber( 0 ), TimeSent( microsec_clock::universal_time() ), @@ -162,6 +161,9 @@ void IcmpPinger::send_echo_request( const IcmpPacketItem icmp_packet ) // Send the request try { + GlobalLogger.info() + << DestinationEndpoint.address().to_string() + << ": sending ping" << endl; const_buffers_1 data = request_buffer.data(); // Block until send the data size_t bytes_sent = Socket.send_to( data, DestinationEndpoint ); diff --git a/src/icmp/icmppinger.h b/src/icmp/icmppinger.h index 5aa0547..ce0c0a7 100644 --- a/src/icmp/icmppinger.h +++ b/src/icmp/icmppinger.h @@ -32,7 +32,7 @@ class IcmpPinger : public Pinger { public: IcmpPinger( - boost::asio::io_service &io_serv, + const IoServiceItem io_serv, const boost::asio::ip::icmp::socket::protocol_type &protocol, const std::string &source_network_interface, const int echo_reply_timeout_in_sec @@ -60,8 +60,6 @@ private: void set_ping_status( PingStatus ping_status ); private: - /// The IO service object, which has the loop event - boost::asio::io_service &IoService; /// The destination host boost::asio::ip::icmp::endpoint DestinationEndpoint; /// Network layer protocol used to ping, IPv4 or IPv6 diff --git a/src/link/linkstatus.cpp b/src/link/linkstatus.cpp index e7b8004..fa500a6 100644 --- a/src/link/linkstatus.cpp +++ b/src/link/linkstatus.cpp @@ -26,14 +26,10 @@ on this file might be covered by the GNU General Public License. #include "boost_assert_handler.h" using namespace std; -using boost::lock_guard; -using boost::mutex; using boost::posix_time::microsec_clock; using boost::posix_time::ptime; using I2n::Logger::GlobalLogger; -typedef lock_guard mutex_lock_guard; - //----------------------------------------------------------------------------- // LinkStatus //----------------------------------------------------------------------------- @@ -63,8 +59,7 @@ LinkStatus::LinkStatus( CurrentLinkStatus( Status_Down ), CurrentNotificationStatus( NotificationStatus_NotReported ), TimeLinkStatusChanged( microsec_clock::universal_time() ), - StatusNotifierCmd( new StatusNotifierCommand( status_notifier_cmd ) ), - Mutex() + StatusNotifierCmd( new StatusNotifierCommand( status_notifier_cmd ) ) { BOOST_ASSERT( 0 <= hosts_down_limit ); BOOST_ASSERT( 0 <= link_up_interval_in_min ); @@ -87,8 +82,6 @@ void LinkStatus::notify_host_up( const string &host_address ) { BOOST_ASSERT( !host_address.empty() ); - mutex_lock_guard lock( Mutex ); - GlobalLogger.info() << "- Host up: " << host_address << endl; add_host_up( host_address ); @@ -114,8 +107,6 @@ void LinkStatus::notify_host_down( const string &host_address ) { BOOST_ASSERT( !host_address.empty() ); - mutex_lock_guard lock( Mutex ); - GlobalLogger.info() << "- Host down: " << host_address << endl; add_host_down( host_address ); diff --git a/src/link/linkstatus.h b/src/link/linkstatus.h index 4d47139..30d247c 100644 --- a/src/link/linkstatus.h +++ b/src/link/linkstatus.h @@ -25,7 +25,6 @@ on this file might be covered by the GNU General Public License. #include #include -#include #include "link/statusnotifiercommand.h" @@ -112,8 +111,6 @@ public: boost::posix_time::ptime TimeLinkStatusChanged; /// Command used to notify the status of the link StatusNotifierCommandItem StatusNotifierCmd; - /// Mutual exclusion variable to avoid data races - boost::mutex Mutex; }; diff --git a/src/main.cpp b/src/main.cpp index 778c839..09881b9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,7 @@ on this file might be covered by the GNU General Public License. #include #include #include -#include +#include #include #include @@ -45,13 +45,16 @@ on this file might be covered by the GNU General Public License. using namespace std; using boost::shared_ptr; -using boost:posix::time_duration; +using boost::posix_time::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; +typedef shared_ptr TimerItem; + +const boost::posix_time::time_duration SIGNAL_CHECK_INTERVAL = boost::posix_time::seconds(1); //----------------------------------------------------------------------------- // Declarations @@ -62,12 +65,38 @@ LinkStatusItem get_status_notifier(const ConfigurationItem&); void init_logger(); void set_log_output(const ConfigurationItem &); DelayMap calc_pinger_delays(const HostList &hosts); -void init_pingers(const ConfigurationItem&, const LinkStatusItem&, PingSchedulerList*); +void init_pingers(const IoServiceItem, const ConfigurationItem&, + const LinkStatusItem&, PingSchedulerList*); void start_pingers(const PingSchedulerList&); void stop_pingers(const PingSchedulerList&); -void block_all_signals(); -void handle_signals(const int default_log_level); +void signal_handler(int param); +void signal_checker( const boost::system::error_code &error ); +void install_signal_handler( const IoServiceItem io_service, const int config_log_level ); +void reset_signal_handlers(); + +// data required for signal handling (SIGINT, SIGTERM, ... ) +struct signal_data_struct +{ + sig_atomic_t signaled_flag; + IoServiceItem io_service; + void (*old_handler_int )(int); + void (*old_handler_term)(int); + void (*old_handler_usr1)(int); + void (*old_handler_usr2)(int); + bool stopped; + TimerItem check_timer; + int config_log_level; + + signal_data_struct(): + signaled_flag( false ), + io_service(), + stopped( false ), + check_timer(), + config_log_level( I2n::Logger::LogLevel::Notice ) + { } + +}; //----------------------------------------------------------------------------- // Definitions //----------------------------------------------------------------------------- @@ -115,8 +144,9 @@ void init_logger() // set default: log at level NOTICE to syslog const int default_log_level = I2n::Logger::LogLevel::Notice; - I2n::Logger::enable_syslog( I2n::Logger::Facility::User ); //lint !e1786 - I2n::Logger::set_log_level( default_log_level ); //lint !e534 + I2n::Logger::enable_syslog( I2n::Logger::Facility::User ); + I2n::Logger::enable_stderr_log( true ); + I2n::Logger::set_log_level( default_log_level ); } void set_log_output( @@ -187,7 +217,7 @@ DelayMap calc_pinger_delays(const HostList &hosts) } void init_pingers( - IoServiceItem io_service, + const IoServiceItem io_service, const ConfigurationItem &configuration, const LinkStatusItem &status_notifier, PingSchedulerList *scheduler_list @@ -254,13 +284,7 @@ void start_pingers( { // start each ping scheduler BOOST_FOREACH( const PingSchedulerItem &scheduler, scheduler_list ) - { - bool started = scheduler->start_pinging_thread(); - if ( !started ) - { - GlobalLogger.error() << "Could not start pinger." << endl; - } - } + scheduler->start_pinging(); } void stop_pingers( @@ -271,129 +295,82 @@ void stop_pingers( GlobalLogger.info() << "Telling all pingers to stop"; BOOST_FOREACH( const PingSchedulerItem &scheduler, scheduler_list ) { - scheduler->stop_pinging_thread(); + scheduler->stop_pinging(); } - - GlobalLogger.info() << "Waiting for threads to shut down"; - BOOST_FOREACH( const PingSchedulerItem &scheduler, scheduler_list ) - { - scheduler->wait_pinging_thread(); - } - GlobalLogger.info() << "All ping threads are gone"; } -/** - * @brief Block all signals so created threads inherit that signal mask. - * - * @return void - **/ -void block_all_signals() -{ - sigset_t all_signals; - int result = sigfillset( &all_signals ); - if ( result == -1 ) { - GlobalLogger.error() << "Sigfillset failed." << endl; - } - result = sigprocmask( SIG_SETMASK, &all_signals, NULL ); - if ( result == -1 ) { - throw runtime_error( "Can't block signals" ); - } +// the one instance of signal_data_struct +signal_data_struct signal_data; + +void signal_handler(int param) +{ + GlobalLogger.info() << "signal handler called with param " << param << endl; + signal_data.signaled_flag = param; } -/** - * @brief Wait until a signal receives and act upon it - * - * @param default_log_level - * - * @return void - **/ -void handle_signals( const int default_log_level ) +void signal_checker( const boost::system::error_code &error ) { - // Wait for signals - sigset_t all_signals; - int result = sigfillset( &all_signals ); - if ( result == -1 ) { - GlobalLogger.error() << "Sigfillset failed." << endl; - } + bool want_stop = false; - // Synchronously process signals - bool want_quit = false; - while ( !want_quit ) - { - int signal_number = 0; - int err = sigwait( &all_signals, &signal_number ); - if (!err) + if ( error ) + { // there was an error in the timer + if ( error == boost::asio::error::operation_aborted ) { - if ( signal_number == SIGUSR1 ) - { - int new_log_level = I2n::Logger::get_log_level()+1; - I2n::Logger::set_log_level( new_log_level ); //lint !e534 - GlobalLogger.info() << "Increased log level to " - << I2n::Logger::get_log_level_string(); - } - else if ( signal_number == SIGUSR2 ) - { - I2n::Logger::set_log_level( default_log_level ); //lint !e534 - GlobalLogger.info() << "Reset log level to normal (" - << I2n::Logger::get_log_level_string() << ")"; - } - else if ( ( signal_number == SIGTERM ) || ( signal_number == SIGINT )) - { - want_quit = true; - } + GlobalLogger.error() << "Signal check timer was cancelled! Stopping io_service" << endl; + want_stop = true; } else { - want_quit = true; + GlobalLogger.error() << "not implemented yet! Stopping io_service" << endl; + want_stop = true; } } -} + else if ( signal_data.signaled_flag ) + { // so there has been a signal --> check which one it was -// 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; + // quickly copy and reset signal flag + sig_atomic_t signaled_flag = signal_data.signaled_flag; + signal_data.signaled_flag = 0; -void signal_handler(int param) -{ - GlobalLogger.info() << "signal handler called with param " << param << endl; - signal_data.signaled_flag = param; -} + if ( signaled_flag == SIGUSR1 ) + { + int new_log_level = I2n::Logger::get_log_level()+1; + I2n::Logger::set_log_level( new_log_level ); + GlobalLogger.info() << "Increased log level to " + << I2n::Logger::get_log_level_string(); + } + else if ( signaled_flag == SIGUSR2 ) + { + I2n::Logger::set_log_level( signal_data.config_log_level ); + GlobalLogger.info() << "Reset log level to normal (" + << I2n::Logger::get_log_level_string() << ")"; + } + else if ( ( signaled_flag == SIGTERM ) || ( signaled_flag == SIGINT )) + { + GlobalLogger.info() << "Received signal SIGINT/SIGTERM --> will stop" << endl; + want_stop = true; + } + } -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; + if ( want_stop ) + { // interrupt infinite loop in main and asio event loop + signal_data.stopped = true; + signal_data.io_service->stop(); } 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() + { // re-schedule timer + GlobalLogger.debug() << "Setting another signal timer" << endl; + signal_data.check_timer->expires_from_now( SIGNAL_CHECK_INTERVAL ); + signal_data.check_timer->async_wait( signal_checker ); } } -bool install_signal_handler( IoServiceItem io_service, - const time_duration &check_interval ) +/// register own signal handlers; see reset_signal_handlers for undo +void install_signal_handler( const IoServiceItem io_service, const int config_log_level ) { signal_data.signaled_flag = 0; + signal_data.config_log_level = config_log_level; // install own signal handlers signal_data.old_handler_int = signal(SIGINT, signal_handler); @@ -404,28 +381,50 @@ bool install_signal_handler( IoServiceItem io_service, 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) ); + throw runtime_error( string("Failed to install signal handler: ") + string(strerror(errno)) ); + + // create a timer and a shared pointer to it, so it does not get out of scope + TimerItem check_timer( new boost::asio::deadline_timer( *io_service ) ); - // add timer to io_service that calls signal_checker - signal_data.check_interval = check_interval; + // remember the io_service and the timer signal_data.io_service = io_service; - signal_data.check_timer( io_service ); - signal_data.check_timer.expires_from_now( check_interval ); + signal_data.check_timer = check_timer; - // start timer - signal_data.check_timer.async_wait( signal_checker ); + // set the timer + check_timer->expires_from_now( SIGNAL_CHECK_INTERVAL ); + check_timer->async_wait( signal_checker ); + GlobalLogger.debug() << "signal timer set" << endl; } -int main( int argc, const char *argv[] ) +/// reset handlers to the ones saved in install_signal_handler +void reset_signal_handlers() { - // Block all signals before creating any threads - block_all_signals(); + void (*old_handler_int)(int); + void (*old_handler_term)(int); + void (*old_handler_usr1)(int); + void (*old_handler_usr2)(int); + old_handler_int = signal(SIGINT , signal_data.old_handler_int); + old_handler_term = signal(SIGTERM, signal_data.old_handler_term); + old_handler_usr1 = signal(SIGUSR1, signal_data.old_handler_usr1); + old_handler_usr2 = signal(SIGUSR2, signal_data.old_handler_usr2); + + if ( old_handler_int == SIG_ERR || + old_handler_term == SIG_ERR || + old_handler_usr1 == SIG_ERR || + old_handler_usr2 == SIG_ERR ) + throw runtime_error( string("Failed to reset signal handler: ") + string(strerror(errno)) ); +} + +int main( int argc, const char *argv[] ) +{ init_logger(); GlobalLogger.debug() << "logger initiated with default config"; PingSchedulerList scheduler_list; + IoServiceItem io_service; int ret_code = 0; + unsigned n_exceptions = 0; try { ConfigurationItem configuration = get_configuration( argc, argv ); @@ -436,7 +435,7 @@ int main( int argc, const char *argv[] ) } int log_level = configuration->get_log_level(); - I2n::Logger::set_log_level( log_level ); //lint !e534 + I2n::Logger::set_log_level( log_level ); GlobalLogger.info() << "Set LogLevel to " << I2n::Logger::get_log_level_string() << endl; set_log_output( configuration ); @@ -450,38 +449,47 @@ int main( int argc, const char *argv[] ) LinkStatusItem status_notifier = get_status_notifier( configuration ); - IoServiceItem io_service( new boost::asio::io_service() ); + IoServiceItem io_service_temp( new boost::asio::io_service() ); + io_service_temp.swap( io_service ); + io_service_temp.reset(); init_pingers( io_service, configuration, status_notifier, &scheduler_list ); - //start_pingers( scheduler_list ); - - install_signal_handler( io_service ); + install_signal_handler( io_service, log_level ); + start_pingers( scheduler_list ); } catch ( const std::exception &ex ) { GlobalLogger.error() << "Uncaught exception. " << ex.what() << endl; ret_code = 1; + ++n_exceptions; } catch (...) { GlobalLogger.error() << "Caught unknown exception!" << endl; ret_code = 2; + ++n_exceptions; } - // call boost::asio main event loop, ignoring exceptions - while ( true ) + if ( ret_code == 0 ) { - try + // call boost::asio main event loop, catching exceptions + while ( !signal_data.stopped ) { - 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; + try + { + GlobalLogger.info() << "starting/continuing io_service main loop" << endl; + io_service->run(); + } + catch ( const std::exception &ex ) + { + ++n_exceptions; + GlobalLogger.error() << "Caught exception, will continue. " << ex.what() << endl; + } + catch (...) { + ++n_exceptions; + GlobalLogger.error() << "Caught unknown exception, will continue!" << endl; + } } } @@ -490,6 +498,7 @@ int main( int argc, const char *argv[] ) { GlobalLogger.info() << "Cleaning up" << endl; stop_pingers( scheduler_list ); + reset_signal_handlers(); } catch ( const std::exception &ex ) { @@ -501,6 +510,7 @@ int main( int argc, const char *argv[] ) ret_code += 8; } - GlobalLogger.notice() << "Pingcheck done" << endl; + GlobalLogger.notice() << "Pingcheck done " << endl; + GlobalLogger.debug() << "In main loop, had " << n_exceptions << " exception[s]" << endl; return ret_code; } diff --git a/src/tcp/tcppinger.cpp b/src/tcp/tcppinger.cpp index ade4d30..fa99849 100644 --- a/src/tcp/tcppinger.cpp +++ b/src/tcp/tcppinger.cpp @@ -66,17 +66,16 @@ using I2n::Logger::GlobalLogger; * @param echo_reply_timeout_in_sec The amount of time to wait for a reply. */ TcpPinger::TcpPinger( - io_service &io_serv, + const IoServiceItem io_serv, const tcp_raw_protocol::socket::protocol_type &protocol, const string &source_network_interface_name, const int rst_reply_timeout_in_sec ) : - IoService( io_serv ), DestinationEndpoint(), Protocol( protocol ), - Socket( IoService, Protocol ), + Socket( *io_serv, Protocol ), NetInterface( source_network_interface_name, Socket ), - TcpSegmentReceiveTimer( IoService ), + TcpSegmentReceiveTimer( *io_serv ), Identifier( 0 ), SequenceNumber( 0 ), TimeSent( microsec_clock::universal_time() ), diff --git a/src/tcp/tcppinger.h b/src/tcp/tcppinger.h index 914322c..690fe29 100644 --- a/src/tcp/tcppinger.h +++ b/src/tcp/tcppinger.h @@ -45,7 +45,7 @@ class TcpPinger : public Pinger { public: TcpPinger( - boost::asio::io_service &io_serv, + const IoServiceItem io_serv, const boost::asio::ip::tcp_raw_protocol::socket::protocol_type &protocol, const std::string &source_network_interface_name, const int rst_reply_timeout_in_sec @@ -81,8 +81,6 @@ private: void set_ping_status( PingStatus ping_status ); private: - /// IO service object, which has the loop event - boost::asio::io_service &IoService; /// The destination host boost::asio::ip::tcp_raw_protocol::endpoint DestinationEndpoint; /// Network layer protocol used to ping, IPv4 or IPv6