libmoost
|
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__