#include <boost/shared_ptr.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/numeric/conversion/cast.hpp>
+#include <boost/date_time/posix_time_types.hpp>
#include <daemonfunc.hpp>
#include <logfunc.hpp>
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<int, float> IntervalCountPair;
typedef std::map<int, float> DelayMap;
+typedef shared_ptr<boost::asio::io_service> IoServiceItem;
//-----------------------------------------------------------------------------
// Declarations
}
void init_pingers(
+ IoServiceItem io_service,
const ConfigurationItem &configuration,
const LinkStatusItem &status_notifier,
PingSchedulerList *scheduler_list
PingSchedulerItem scheduler(
new PingScheduler(
+ io_service,
network_interface,
destination_address,
destination_port,
bool started = scheduler->start_pinging_thread();
if ( !started )
{
- GlobalLogger.error() << "Error: could not start pinger."
- << endl;
+ GlobalLogger.error() << "Could not start pinger." << endl;
}
}
}
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 );
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
}
}
+// 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
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;
}