31 static bool s_exit_handler_print =
true;
32 static bool s_exit_handler_active =
false;
33 static bool s_exit_handler_backtrace =
false;
34 static bool s_exit_handler_sleep_on_fatal =
false;
36 template<
class T>
union func_cast {
39 explicit func_cast(T t) { fun = t; }
40 explicit func_cast(
void* t) { ptr = t; }
64 typedef std::map<int, sig_handler_t>
SigMap;
77 void install(
int num,
const std::string& name,
struct sigaction& action);
81 int unsubscribe(
int signum,
void* user_context);
83 void back_trace(
int );
85 static void handler(
int signum, siginfo_t *
info,
void * );
98 static std::unique_ptr<implementation> imp;
100 imp = std::make_unique<implementation>();
107 struct sigaction new_action;
108 sigemptyset(&new_action.sa_mask);
109 new_action.sa_handler = 0;
110 new_action.sa_sigaction = handler;
111 new_action.sa_flags = SA_SIGINFO;
113 install(SIGILL,
"SIGILL", new_action);
114 install(SIGINT,
"SIGINT", new_action);
115 install(SIGTERM,
"SIGTERM", new_action);
116 install(SIGHUP,
"SIGHUP", new_action);
118 install(SIGQUIT,
"SIGQUIT", new_action);
119 install(SIGBUS,
"SIGBUS", new_action);
120 install(SIGXCPU,
"SIGXCPU", new_action);
121 sigaddset(&new_action.sa_mask,SIGSEGV);
122 sigaddset(&new_action.sa_mask,SIGABRT);
123 sigaddset(&new_action.sa_mask,SIGFPE);
124 install(SIGABRT,
"SIGABRT", new_action);
125 install(SIGFPE,
"SIGFPE", new_action);
126 install(SIGSEGV,
"SIGSEGV", new_action);
131 if ( m_map.empty() ) {
134 auto ihandler = m_map.find(signum);
135 if ( ihandler == m_map.end() ) {
137 struct sigaction new_action;
138 sigemptyset(&new_action.sa_mask);
139 new_action.sa_handler = 0;
141 new_action.sa_flags = SA_SIGINFO;
142 ::snprintf(text,
sizeof(text),
"%08X",signum);
143 install(signum, text, new_action);
144 ihandler = m_map.find(signum);
146 if ( ihandler != m_map.end() ) {
148 ihandler->second.user_handlers.emplace_back(entry);
156 auto ihandler = m_map.find(signum);
157 if ( ihandler != m_map.end() ) {
158 auto & handlers = ihandler->second.user_handlers;
159 for(
auto it = handlers.begin(); it != handlers.end(); ++it ) {
160 if ( it->user_context == user_context ) {
171 if ( s_exit_handler_backtrace ) {
174 int bt_size = ::backtrace(bt,
sizeof(bt) /
sizeof(
void *));
175 size_t len = ::snprintf(text,
sizeof(text),
"\n[INFO] (ExitSignalHandler) %s\n",
176 "---------------------- Backtrace ----------------------\n");
177 text[
sizeof(text)-2] =
'\n';
178 text[
sizeof(text)-1] = 0;
179 ::write(STDERR_FILENO, text, len);
180 len = ::snprintf(text,
sizeof(text),
"[INFO] Number of elements in backtrace: %d\n", bt_size);
181 text[
sizeof(text)-2] =
'\n';
182 text[
sizeof(text)-1] = 0;
183 ::write(STDERR_FILENO, text, len);
184 ::backtrace_symbols_fd(bt, bt_size, STDERR_FILENO);
185 for (
int i = 0; i < bt_size; i++) {
186 len = ::snprintf(text,
sizeof(text),
"[INFO] (SignalHandler) %02d --> %p\n", i, bt[i]);
187 text[
sizeof(text)-2] =
'\n';
188 text[
sizeof(text)-1] = 0;
189 ::write(STDERR_FILENO, text, len);
196 auto& action_entry = m_map[num];
197 int res = ::sigaction (num, &action, &action_entry.old_action);
200 auto len = ::snprintf(text,
sizeof(text),
"Failed to install exit handler for %s", name.c_str());
201 text[
sizeof(text)-2] =
'\n';
202 text[
sizeof(text)-1] = 0;
203 ::write(STDERR_FILENO, text, len);
206 action_entry.handler_action = action;
207 action_entry.name = name;
212 SigMap& m = instance().m_map;
213 SigMap::iterator iter_handler = m.find(signum);
214 s_exit_handler_active =
true;
215 if ( iter_handler != m.end() ) {
216 auto hdlr = iter_handler->second.old_action.sa_handler;
217 func_cast<void (*)(int)> dsc0(hdlr);
218 func_cast<void (*)(int,siginfo_t*,
void*)> dsc(dsc0.ptr);
220 if ( s_exit_handler_print ) {{
222 size_t len = ::snprintf(text,
sizeof(text),
223 "[FATAL] (SignalHandler) Handle signal: %d [%s] Old action:%p Mem:%p Code:%08X\n",
224 signum,iter_handler->second.name.c_str(),dsc.ptr,
info->si_addr,
info->si_code);
225 text[
sizeof(text)-2] =
'\n';
226 text[
sizeof(text)-1] = 0;
227 ::write(STDERR_FILENO,text,len);
229 if ( s_exit_handler_sleep_on_fatal ) {
230 bool _s_sleep =
true;
231 len = ::snprintf(text,
sizeof(text),
232 "[FATAL] (SignalHandler) Sleeping for debugging.... %s\n",
233 _s_sleep ?
"YES" :
"NO");
234 text[
sizeof(text)-2] =
'\n';
235 text[
sizeof(text)-1] = 0;
236 ::write(STDERR_FILENO,text,len);
237 while ( _s_sleep ) ::usleep(100000);
240 if ( !iter_handler->second.user_handlers.empty() ) {
241 auto& handlers = iter_handler->second.user_handlers;
242 for(
auto ih = handlers.rbegin(); ih != handlers.rend(); ++ih ) {
243 if ( ih->user_handler ) {
244 bool ret = (*(ih->user_handler))(ih->user_context, signum);
251 auto& entry = iter_handler->second.old_action;
252 if ( entry.sa_handler )
253 (*entry.sa_handler)(signum);
254 else if ( entry.sa_sigaction )
255 (*entry.sa_sigaction)(signum,
info, ptr);
258 if ( signum == SIGSEGV || signum == SIGBUS || signum == SIGILL || signum == SIGABRT ) {
259 instance().back_trace(signum);
261 else if (
info->si_signo == SIGSEGV ||
info->si_signo == SIGBUS ||
info->si_signo == SIGILL ||
info->si_signo == SIGABRT ) {
262 instance().back_trace(
info->si_signo);
265 if ( signum == SIGINT || signum == SIGHUP || signum == SIGFPE || signum == SIGPIPE ) {
266 if ( dsc.fun && (dsc0.fun != SIG_IGN) )
267 dsc.fun(signum,
info, ptr);
268 else if ( signum == SIGHUP )
271 else if ( signum == SIGSEGV && hdlr && hdlr != SIG_IGN && hdlr != SIG_DFL ) {
274 else if ( hdlr && hdlr != SIG_IGN && dsc.fun ) {
275 dsc.fun(signum,
info, ptr);
277 else if ( hdlr == SIG_DFL ) {
281 s_exit_handler_active =
false;
295 auto& imp = implementation::instance();
296 struct sigaction old_action { };
297 printout(INFO,
"SignalHandler",
"++ Re-apply signal handlers");
298 for(
const auto& e : imp.m_map ) {
299 ::sigaction (e.first, &e.second.handler_action, &old_action);
300 printout(DEBUG,
"SignalHandler",
301 "++ Re-apply signal handler for %-10s [%3ld entries]",
302 e.second.name.c_str(), e.second.user_handlers.size());
308 return implementation::instance().subscribe(sig_num, param, handler) == 1;