libmoost
/home/mhx/git/github/libmoost/include/moost/process/quit_handler.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef MOOST_UTILS_QUIT_HANDLER_HPP__
00029 #define MOOST_UTILS_QUIT_HANDLER_HPP__
00030 
00031 #include <csignal>
00032 #include <cstdlib>
00033 
00034 #include <boost/function.hpp>
00035 
00036 #include "hup_handler.hpp"
00037 
00038 namespace moost { namespace process {
00039 
00057    //
00059 
00060    class quit_handler
00061    {
00062    private:
00063       // A Meyers Singleton (http://bit.ly/EsS4p)
00064       static quit_handler & get_single_instance()
00065       {
00066          static quit_handler quit_handler;
00067          return quit_handler;
00068       }
00069 
00070    public:
00071       typedef boost::function<void ()> handler_t;
00072 
00073       // Set the customer handler.
00074       static void set(handler_t const & handler, bool trap_abort = true, bool trap_hup = false)
00075       {
00076          quit_handler & quit_handler = quit_handler::get_single_instance();
00077          quit_handler.handler_ = handler;
00078          quit_handler.register_handler(trap_abort);
00079 
00080          if(trap_hup)
00081          {
00082             // Register with hup_handler, as this knows all about SIGHUP
00083             hup_handler::set(handler);
00084          }
00085       }
00086 
00087    private:
00088       handler_t handler_;
00089 
00090       // This is the proxy handler, which calls the custom handler
00091       static void sighandler(int)
00092       {
00093          quit_handler & quit_handler = quit_handler::get_single_instance();
00094 
00095          if(quit_handler.handler_)
00096          {
00097             quit_handler.handler_();
00098          }
00099       }
00100 
00101       // Register the proxy handler
00102       struct sigaction sa_;
00103       void register_handler(bool trap_abort)
00104       {
00105          memset(&sa_, 0, sizeof(sa_));
00106          sa_.sa_handler = quit_handler::sighandler;
00107 
00108          sigemptyset(&sa_.sa_mask);
00109          sa_.sa_flags = SIG_BLOCK;
00110 
00111          // These are the signals we'll block whilst the handlers being called
00112          sigaddset(&sa_.sa_mask, SIGINT);
00113          sigaddset(&sa_.sa_mask, SIGTERM);
00114          sigaddset(&sa_.sa_mask, SIGQUIT);
00115 
00116          if (trap_abort) { sigaddset(&sa_.sa_mask, SIGABRT); }
00117 
00118          // These are the signals we'll trap and handle
00119          sigaction(SIGINT, &sa_, NULL);
00120          sigaction(SIGTERM, &sa_, NULL);
00121          sigaction(SIGQUIT, &sa_, NULL);
00122 
00123          if (trap_abort) { sigaction(SIGABRT, &sa_, NULL); }
00124       }
00125    };
00126 
00127 }}
00128 
00129 #endif // MOOST_UTILS_QUIT_HANDLER_HPP__