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;
 
  * @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,
         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 ),
     AddressResolutionAttempts( 0 ),
     MaxAddressResolutionAttempts( max_address_resolution_attempts ),
     EverHadAnyIP( false ),
-    Ping(),
-    Thread()
+    Ping()
 {
     BOOST_ASSERT( !network_interface.empty() );
     BOOST_ASSERT( !destination_address.empty() );
 
     Ping = PingerFactory::createPinger(
             ping_protocol_list,
-            IoService,
+            io_service,
             network_interface,
             destination_address,
             destination_port,
 {
 }
 
-/**
- * @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()
 {
     }
     else
         resolve_and_ping();
-
-    // event processing loop, it is a blocking call!
-    IoService.run();                                                                                    //lint !e534
-    GlobalLogger.info() << "Ping thread was stopped.";
 }
 
 
 
 #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 <boost/date_time/posix_time/posix_time_types.hpp>
 
 #include <daemonfunc.hpp>
 #include <logfunc.hpp>
 
 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<int, float> IntervalCountPair;
 typedef std::map<int, float> DelayMap;
 typedef shared_ptr<boost::asio::io_service> IoServiceItem;
+typedef shared_ptr<boost::asio::deadline_timer> TimerItem;
+
+const boost::posix_time::time_duration SIGNAL_CHECK_INTERVAL = boost::posix_time::seconds(1);
 
 //-----------------------------------------------------------------------------
 // Declarations
 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
 //-----------------------------------------------------------------------------
     // 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(
 }
 
 void init_pingers(
-        IoServiceItem io_service,
+        const IoServiceItem io_service,
         const ConfigurationItem &configuration,
         const LinkStatusItem &status_notifier,
         PingSchedulerList *scheduler_list
 {
     // 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(
     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);
           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 );
         }
 
         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 );
 
         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;
+            }
         }
     }
 
     {
         GlobalLogger.info() << "Cleaning up" << endl;
         stop_pingers( scheduler_list );
+        reset_signal_handlers();
     }
     catch ( const std::exception &ex )
     {
         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;
 }