| 284 | } |
| 285 | |
| 286 | bool InitSignalHandlerUnlocked(int signum) { |
| 287 | enum InitState { |
| 288 | UNINITIALIZED, |
| 289 | INIT_ERROR, |
| 290 | INITIALIZED |
| 291 | }; |
| 292 | static InitState state = UNINITIALIZED; |
| 293 | |
| 294 | // If we've already registered a handler, but we're being asked to |
| 295 | // change our signal, unregister the old one. |
| 296 | if (signum != g_stack_trace_signum && state == INITIALIZED) { |
| 297 | struct sigaction old_act; |
| 298 | PCHECK(sigaction(g_stack_trace_signum, nullptr, &old_act) == 0); |
| 299 | if (old_act.sa_sigaction == &HandleStackTraceSignal) { |
| 300 | signal(g_stack_trace_signum, SIG_DFL); |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | // If we'd previously had an error, but the signal number |
| 305 | // is changing, we should mark ourselves uninitialized. |
| 306 | if (signum != g_stack_trace_signum) { |
| 307 | g_stack_trace_signum = signum; |
| 308 | state = UNINITIALIZED; |
| 309 | } |
| 310 | |
| 311 | if (state == UNINITIALIZED) { |
| 312 | struct sigaction old_act; |
| 313 | PCHECK(sigaction(g_stack_trace_signum, nullptr, &old_act) == 0); |
| 314 | if (old_act.sa_handler != SIG_DFL && |
| 315 | old_act.sa_handler != SIG_IGN) { |
| 316 | state = INIT_ERROR; |
| 317 | LOG(WARNING) << "signal handler for stack trace signal " |
| 318 | << g_stack_trace_signum |
| 319 | << " is already in use: " |
| 320 | << "Kudu will not produce thread stack traces."; |
| 321 | } else { |
| 322 | // No one appears to be using the signal. This is racy, but there is no |
| 323 | // atomic swap capability. |
| 324 | struct sigaction act; |
| 325 | memset(&act, 0, sizeof(act)); |
| 326 | act.sa_sigaction = &HandleStackTraceSignal; |
| 327 | act.sa_flags = SA_SIGINFO | SA_RESTART; |
| 328 | struct sigaction old_act; |
| 329 | CHECK_ERR(sigaction(g_stack_trace_signum, &act, &old_act)); |
| 330 | sighandler_t old_handler = old_act.sa_handler; |
| 331 | if (old_handler != SIG_IGN && |
| 332 | old_handler != SIG_DFL) { |
| 333 | LOG(FATAL) << "raced against another thread installing a signal handler"; |
| 334 | } |
| 335 | state = INITIALIZED; |
| 336 | } |
| 337 | } |
| 338 | return state == INITIALIZED; |
| 339 | } |
| 340 | |
| 341 | #ifdef __linux__ |
| 342 | GoogleOnceType g_prime_libunwind_once; |
no test coverage detected