Handle signals in a thread safe way
authorThomas Jarosch <thomas.jarosch@intra2net.com>
Tue, 3 May 2011 12:53:35 +0000 (14:53 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Tue, 3 May 2011 12:53:35 +0000 (14:53 +0200)
src/main.cpp

index 263678d..ee66765 100644 (file)
@@ -4,7 +4,6 @@
 #include <iostream>
 
 #include <boost/asio.hpp>
-#include <boost/asio/posix/signal_handler.hpp>
 #include <boost/foreach.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -21,6 +20,9 @@ using boost::asio::io_service;
 using boost::shared_ptr;
 using I2n::Logger::GlobalLogger;
 
+// TODO: Change back to Notice log level
+const int default_log_level = I2n::Logger::LogLevel::Info;
+
 ConfigurationItem get_configuration(
         int argc,
         char *argv[]
@@ -59,14 +61,8 @@ LinkStatusAnalyzerItem get_status_notifier(
 
 void init_logger()
 {
-    I2n::Logger::enable_syslog( I2n::Logger::Facility::User );
-    // TODO: Change back to Notice log level
-    I2n::Logger::set_log_level( I2n::Logger::LogLevel::Info );
-}
-
-void init_signal_handler()
-{
-    // TODO
+    I2n::Logger::enable_syslog( I2n::Logger::Facility::User );                           //lint !e1786
+    I2n::Logger::set_log_level( default_log_level );                                          //lint !e534
 }
 
 void init_pingers(
@@ -133,18 +129,57 @@ void stop_pingers(
     }
 }
 
-void handle_SIGINT(
-        const boost::system::error_code &ec,
-        int signal
-)
+/**
+ * @brief Block all signals so created threads inherit that signal mask.
+ *
+ * @return void
+ **/
+void block_all_signals()
 {
-//    cerr << "handle_SIGINT" << endl;
-    // TODO may I call stop_pingers() them from here?
-//    stop_pingers();
+    sigset_t all_signals;
+    sigfillset(&all_signals);
+
+    if (sigprocmask(SIG_SETMASK, &all_signals, NULL) == -1)
+        throw runtime_error("Can't block signals");
+}
+
+/**
+ * @brief Wait until a signal receives and act upon it
+ *
+ * @return void
+ **/
+void handle_signals()
+{
+    // Wait for signals
+    sigset_t all_signals;
+    sigfillset(&all_signals);
+
+    // Synchronously process signals
+    bool want_quit = false;
+    while (!want_quit)
+    {
+        int signal = 0;
+        int err = sigwait(&all_signals, &signal);
+        if (!err)
+        {
+            if (signal == SIGUSR1)
+                I2n::Logger::set_log_level( I2n::Logger::get_log_level()+1 );                      //lint !e534
+            else if (signal == SIGUSR2)
+                I2n::Logger::set_log_level( default_log_level );                                          //lint !e534
+            else if (signal == SIGTERM || signal == SIGINT)
+                want_quit = true;
+            else if (signal == SIGHUP)
+                std::cerr << "DEBUG: Caught HUP signal" << std::endl;
+        } else
+            want_quit = true;
+    }
 }
 
 int main( int argc, char *argv[] )
 {
+    // Block all signals before creating any threads
+    block_all_signals();
+
     init_logger();
 
     ConfigurationItem configuration = get_configuration( argc, argv );
@@ -163,12 +198,11 @@ int main( int argc, char *argv[] )
 
         start_pingers( scheduler_list );
 
-        // TODO signal stuff to method
-        io_service io_serv;
-        boost::asio::posix::signal_handler sh( io_serv );
-        sh.add_signal( SIGINT );
-        sh.async_wait( handle_SIGINT );
-        io_serv.run();
+        // React to signals (main thread will sleep)
+        handle_signals();
+
+        // TODO: Shut down threads
+        std::cerr << "DEBUG: Shutting down" << std::endl;
     }
 
     return 0;