|
Sierra Toolkit
Version of the Day
|
00001 00010 #include <stdexcept> 00011 #include <vector> 00012 #include <iostream> 00013 00014 #include <stk_util/diag/SignalHandler.hpp> 00015 00016 #include <signal.h> 00017 #include <time.h> 00018 00019 extern "C" { 00020 static void signal_handler(int signal, siginfo_t *sip, void *ucp) 00021 { 00022 // This routine is called for all signals... 00023 // Just a C-callable wrapper around a call to the true signal handler... 00024 sierra::SignalHandler::instance().handle_signal(signal); 00025 } 00026 } 00027 00028 namespace sierra { 00029 00030 namespace { 00031 00032 int 00033 convert_name_to_signal( 00034 const String & signal) 00035 { 00036 if (signal == "SIGABRT" || signal == "SIGKILL") { 00037 return -1; 00038 } 00039 00040 #if defined(SIGILL) 00041 if (signal == "SIGILL") return SIGILL; 00042 #endif 00043 #if defined(SIGSEGV) 00044 if (signal == "SIGSEGV") return SIGSEGV; 00045 #endif 00046 #if defined(SIGALRM) 00047 if (signal == "SIGALRM") return SIGALRM; 00048 #endif 00049 #if defined(SIGFPE) 00050 if (signal == "SIGFPE") return SIGFPE; 00051 #endif 00052 #if defined(SIGHUP) 00053 if (signal == "SIGHUP") return SIGHUP; 00054 #endif 00055 #if defined(SIGINT) 00056 if (signal == "SIGINT") return SIGINT; 00057 #endif 00058 #if defined(SIGPIPE) 00059 if (signal == "SIGPIPE") return SIGPIPE; 00060 #endif 00061 #if defined(SIGQUIT) 00062 if (signal == "SIGQUIT") return SIGQUIT; 00063 #endif 00064 #if defined(SIGTERM) 00065 if (signal == "SIGTERM") return SIGTERM; 00066 #endif 00067 #if defined(SIGUSR1) 00068 if (signal == "SIGUSR1") return SIGUSR1; 00069 #endif 00070 #if defined(SIGUSR2) 00071 if (signal == "SIGUSR2") return SIGUSR2; 00072 #endif 00073 return -2; 00074 } 00075 00076 } // namespace <unnamed> 00077 00078 00079 SignalHandler & 00080 SignalHandler::instance() { 00081 static SignalHandler signal_handler; 00082 00083 return signal_handler; 00084 } 00085 00086 00087 void 00088 SignalHandler::handle_signal( 00089 int signal) 00090 { 00091 typedef std::vector<const HandlerMap::value_type *> HandlerList; 00092 00093 time_t now = ::time(NULL); 00094 00095 std::cerr << "Sierra received signal " << signal << " at " << ::ctime(&now) << std::endl; 00096 00097 HandlerList handlers; 00098 00099 std::pair<HandlerMap::const_iterator, HandlerMap::const_iterator> range = m_handlerMap.equal_range(signal); 00100 00101 for (HandlerMap::const_iterator pos = range.first; pos != range.second; ++pos) 00102 handlers.push_back(&*pos); 00103 00104 for (HandlerList::const_iterator it = handlers.begin(); it != handlers.end(); ++it) { 00105 CallbackBase &obj = *(*it)->second; 00106 obj(); 00107 } 00108 } 00109 00110 00111 bool 00112 SignalHandler::check_signal_name( 00113 const String & signal) 00114 { 00115 int isignal = convert_name_to_signal(signal); 00116 return (isignal >= 0); 00117 } 00118 00119 00120 void 00121 SignalHandler::add_handler( 00122 const String & signal, 00123 CallbackBase & callback) 00124 { 00125 int isignal = convert_name_to_signal(signal); 00126 if (isignal >= 0) { 00127 add_handler(isignal, callback); 00128 } 00129 else if (isignal == -1) 00130 throw std::runtime_error("signal cannot be handled"); 00131 else if (isignal == -2) 00132 throw std::runtime_error("signal name invalid"); 00133 else 00134 throw std::logic_error("invalid value from convert_node_to_signal()"); 00135 } 00136 00137 00138 void 00139 SignalHandler::add_handler( 00140 int signal, 00141 CallbackBase & callback) 00142 { 00143 // See if already handling this signal... 00144 if (m_handlerMap.find(signal) == m_handlerMap.end()) { 00145 // Tell OS that we want to handle this signal... 00146 struct sigaction action; 00147 struct sigaction *old_action = new struct sigaction; 00148 00149 action.sa_sigaction = signal_handler; 00150 sigemptyset(&action.sa_mask); 00151 action.sa_flags = SA_SIGINFO; 00152 ::sigaction(signal, &action, old_action); 00153 m_oldActionMap.insert(OldActionMap::value_type(signal, old_action)); 00154 } 00155 m_handlerMap.insert(HandlerMap::value_type(signal, &callback)); 00156 } 00157 00158 00159 void 00160 SignalHandler::remove_handler( 00161 int signal, 00162 CallbackBase & callback) 00163 { 00164 typedef std::pair<HandlerMap::iterator, HandlerMap::iterator> HandlerRange; 00165 00166 HandlerRange handler_range = m_handlerMap.equal_range(signal); 00167 for (HandlerMap::iterator it = handler_range.first; it != handler_range.second; ) 00168 if ((*it).second == &callback) { 00169 HandlerMap::iterator erase_it = it++; 00170 m_handlerMap.erase(erase_it); 00171 } 00172 else 00173 ++it; 00174 00175 if (m_handlerMap.find(signal) == m_handlerMap.end()) { 00176 OldActionMap::iterator it = m_oldActionMap.find(signal); 00177 if (it != m_oldActionMap.end()) { 00178 ::sigaction(signal, (*it).second, NULL); 00179 delete (*it).second; 00180 m_oldActionMap.erase(it); 00181 } 00182 } 00183 } 00184 00185 00186 void 00187 SignalHandler::remove_handler( 00188 const String & signal, 00189 CallbackBase & callback) 00190 { 00191 int isignal = convert_name_to_signal(signal); 00192 if (isignal >= 0) { 00193 remove_handler(isignal, callback); 00194 } 00195 else if (isignal == -1) 00196 throw std::runtime_error("signal cannot be handled"); 00197 else if (isignal == -2) 00198 throw std::runtime_error("signal name invalid"); 00199 else 00200 throw std::logic_error("invalid value from convert_node_to_signal()"); 00201 } 00202 00203 00204 void 00205 SignalHandler::remove_all_handlers() 00206 { 00207 m_handlerMap.clear(); 00208 00209 for (OldActionMap::iterator it = m_oldActionMap.begin(); it != m_oldActionMap.end(); ++it) { 00210 ::sigaction((*it).first, (*it).second, NULL); 00211 delete (*it).second; 00212 } 00213 m_oldActionMap.clear(); 00214 } 00215 00216 00217 } // namespace sierra