30 static bool s_exit_handler_print =
true;
31 static bool s_exit_handler_active =
false;
32 static bool s_exit_handler_backtrace =
false;
33 static bool s_exit_handler_sleep_on_fatal =
false;
35 template<
class T>
union func_cast {
38 explicit func_cast(T t) { fun = t; }
39 explicit func_cast(
void* t) { ptr = t; }
63 typedef std::map<int, sig_handler_t>
SigMap;
76 void install(
int num,
const std::string& name,
struct sigaction& action);
80 int unsubscribe(
int signum,
void* user_context);
82 void back_trace(
int );
84 static void handler(
int signum, siginfo_t *
info,
void * );
97 static std::unique_ptr<implementation> imp;
99 imp = std::make_unique<implementation>();
106 struct sigaction new_action;
107 sigemptyset(&new_action.sa_mask);
108 new_action.sa_handler = 0;
109 new_action.sa_sigaction = handler;
110 new_action.sa_flags = SA_SIGINFO;
112 install(SIGILL,
"SIGILL", new_action);
113 install(SIGINT,
"SIGINT", new_action);
114 install(SIGTERM,
"SIGTERM", new_action);
115 install(SIGHUP,
"SIGHUP", new_action);
117 install(SIGQUIT,
"SIGQUIT", new_action);
118 install(SIGBUS,
"SIGBUS", new_action);
119 install(SIGXCPU,
"SIGXCPU", new_action);
120 sigaddset(&new_action.sa_mask,SIGSEGV);
121 sigaddset(&new_action.sa_mask,SIGABRT);
122 sigaddset(&new_action.sa_mask,SIGFPE);
123 install(SIGABRT,
"SIGABRT", new_action);
124 install(SIGFPE,
"SIGFPE", new_action);
125 install(SIGSEGV,
"SIGSEGV", new_action);
130 if ( m_map.empty() ) {
133 auto ihandler = m_map.find(signum);
134 if ( ihandler == m_map.end() ) {
136 struct sigaction new_action;
137 sigemptyset(&new_action.sa_mask);
138 new_action.sa_handler = 0;
140 new_action.sa_flags = SA_SIGINFO;
141 ::snprintf(text,
sizeof(text),
"%08X",signum);
142 install(signum, text, new_action);
143 ihandler = m_map.find(signum);
145 if ( ihandler != m_map.end() ) {
147 ihandler->second.user_handlers.emplace_back(entry);
155 auto ihandler = m_map.find(signum);
156 if ( ihandler != m_map.end() ) {
157 auto & handlers = ihandler->second.user_handlers;
158 for(
auto it = handlers.begin(); it != handlers.end(); ++it ) {
159 if ( it->user_context == user_context ) {
170 if ( s_exit_handler_backtrace ) {
173 int bt_size = ::backtrace(bt,
sizeof(bt) /
sizeof(
void *));
174 size_t len = ::snprintf(text,
sizeof(text),
"\n[INFO] (ExitSignalHandler) %s\n",
175 "---------------------- Backtrace ----------------------\n");
176 text[
sizeof(text)-2] =
'\n';
177 text[
sizeof(text)-1] = 0;
178 ::write(STDERR_FILENO, text, len);
179 len = ::snprintf(text,
sizeof(text),
"[INFO] Number of elements in backtrace: %d\n", bt_size);
180 text[
sizeof(text)-2] =
'\n';
181 text[
sizeof(text)-1] = 0;
182 ::write(STDERR_FILENO, text, len);
183 ::backtrace_symbols_fd(bt, bt_size, STDERR_FILENO);
184 for (
int i = 0; i < bt_size; i++) {
185 len = ::snprintf(text,
sizeof(text),
"[INFO] (SignalHandler) %02d --> %p\n", i, bt[i]);
186 text[
sizeof(text)-2] =
'\n';
187 text[
sizeof(text)-1] = 0;
188 ::write(STDERR_FILENO, text, len);
195 auto& action_entry = m_map[num];
196 int res = ::sigaction (num, &action, &action_entry.old_action);
199 auto len = ::snprintf(text,
sizeof(text),
"Failed to install exit handler for %s", name.c_str());
200 text[
sizeof(text)-2] =
'\n';
201 text[
sizeof(text)-1] = 0;
202 ::write(STDERR_FILENO, text, len);
205 action_entry.handler_action = action;
206 action_entry.name = name;
211 SigMap& m = instance().m_map;
212 SigMap::iterator iter_handler = m.find(signum);
213 s_exit_handler_active =
true;
214 if ( iter_handler != m.end() ) {
215 auto hdlr = iter_handler->second.old_action.sa_handler;
216 func_cast<void (*)(int)> dsc0(hdlr);
217 func_cast<void (*)(int,siginfo_t*,
void*)> dsc(dsc0.ptr);
219 if ( s_exit_handler_print ) {{
221 size_t len = ::snprintf(text,
sizeof(text),
222 "[FATAL] (SignalHandler) Handle signal: %d [%s] Old action:%p Mem:%p Code:%08X\n",
223 signum,iter_handler->second.name.c_str(),dsc.ptr,
info->si_addr,
info->si_code);
224 text[
sizeof(text)-2] =
'\n';
225 text[
sizeof(text)-1] = 0;
226 ::write(STDERR_FILENO,text,len);
228 if ( s_exit_handler_sleep_on_fatal ) {
229 bool _s_sleep =
true;
230 len = ::snprintf(text,
sizeof(text),
231 "[FATAL] (SignalHandler) Sleeping for debugging.... %s\n",
232 _s_sleep ?
"YES" :
"NO");
233 text[
sizeof(text)-2] =
'\n';
234 text[
sizeof(text)-1] = 0;
235 ::write(STDERR_FILENO,text,len);
236 while ( _s_sleep ) ::usleep(100000);
239 if ( !iter_handler->second.user_handlers.empty() ) {
240 auto& handlers = iter_handler->second.user_handlers;
241 for(
auto ih = handlers.rbegin(); ih != handlers.rend(); ++ih ) {
242 if ( ih->user_handler ) {
243 bool ret = (*(ih->user_handler))(ih->user_context, signum);
250 auto& entry = iter_handler->second.old_action;
251 if ( entry.sa_handler )
252 (*entry.sa_handler)(signum);
253 else if ( entry.sa_sigaction )
254 (*entry.sa_sigaction)(signum,
info, ptr);
257 if ( signum == SIGSEGV || signum == SIGBUS || signum == SIGILL || signum == SIGABRT ) {
258 instance().back_trace(signum);
260 else if (
info->si_signo == SIGSEGV ||
info->si_signo == SIGBUS ||
info->si_signo == SIGILL ||
info->si_signo == SIGABRT ) {
261 instance().back_trace(
info->si_signo);
264 if ( signum == SIGINT || signum == SIGHUP || signum == SIGFPE || signum == SIGPIPE ) {
265 if ( dsc.fun && (dsc0.fun != SIG_IGN) )
266 dsc.fun(signum,
info, ptr);
267 else if ( signum == SIGHUP )
270 else if ( signum == SIGSEGV && hdlr && hdlr != SIG_IGN && hdlr != SIG_DFL ) {
273 else if ( hdlr && hdlr != SIG_IGN && dsc.fun ) {
274 dsc.fun(signum,
info, ptr);
276 else if ( hdlr == SIG_DFL ) {
280 s_exit_handler_active =
false;
294 auto& imp = implementation::instance();
295 struct sigaction old_action { };
296 printout(INFO,
"SignalHandler",
"++ Re-apply signal handlers");
297 for(
const auto& e : imp.m_map ) {
298 ::sigaction (e.first, &e.second.handler_action, &old_action);
299 printout(DEBUG,
"SignalHandler",
300 "++ Re-apply signal handler for %-10s [%3ld entries]",
301 e.second.name.c_str(), e.second.user_handlers.size());
307 return implementation::instance().subscribe(sig_num, param, handler) == 1;