failure_signal_handler.cc (14071B)
1 // 2 // Copyright 2018 The Abseil Authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // https://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "absl/debugging/failure_signal_handler.h" 18 19 #include "absl/base/config.h" 20 21 #ifdef _WIN32 22 #include <windows.h> 23 #else 24 #include <pthread.h> 25 #include <sched.h> 26 #include <unistd.h> 27 #endif 28 29 #ifdef __APPLE__ 30 #include <TargetConditionals.h> 31 #endif 32 33 #ifdef ABSL_HAVE_MMAP 34 #include <sys/mman.h> 35 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 36 #define MAP_ANONYMOUS MAP_ANON 37 #endif 38 #endif 39 40 #ifdef __linux__ 41 #include <sys/prctl.h> 42 #endif 43 44 #include <algorithm> 45 #include <atomic> 46 #include <cerrno> 47 #include <csignal> 48 #include <cstdio> 49 #include <cstring> 50 #include <ctime> 51 52 #include "absl/base/attributes.h" 53 #include "absl/base/internal/raw_logging.h" 54 #include "absl/base/internal/sysinfo.h" 55 #include "absl/debugging/internal/examine_stack.h" 56 #include "absl/debugging/stacktrace.h" 57 58 #if !defined(_WIN32) && !defined(__wasi__) 59 #define ABSL_HAVE_SIGACTION 60 // Apple WatchOS and TVOS don't allow sigaltstack 61 // Apple macOS has sigaltstack, but using it makes backtrace() unusable. 62 #if !(defined(TARGET_OS_OSX) && TARGET_OS_OSX) && \ 63 !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \ 64 !(defined(TARGET_OS_TV) && TARGET_OS_TV) && !defined(__QNX__) 65 #define ABSL_HAVE_SIGALTSTACK 66 #endif 67 #endif 68 69 // ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 70 // 71 // Checks whether pthread_cpu_number_np is available. 72 #ifdef ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 73 #error ABSL_HAVE_PTHREAD_CPU_NUMBER_NP cannot be directly set 74 #elif defined(__APPLE__) && defined(__has_include) && \ 75 ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ 76 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000) || \ 77 (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ 78 __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140200) || \ 79 (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ 80 __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 70100) || \ 81 (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ 82 __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 140200)) 83 #define ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 1 84 #endif 85 86 namespace absl { 87 ABSL_NAMESPACE_BEGIN 88 89 ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options; 90 91 // Resets the signal handler for signo to the default action for that 92 // signal, then raises the signal. 93 static void RaiseToDefaultHandler(int signo) { 94 signal(signo, SIG_DFL); 95 raise(signo); 96 } 97 98 struct FailureSignalData { 99 const int signo; 100 const char* const as_string; 101 #ifdef ABSL_HAVE_SIGACTION 102 struct sigaction previous_action; 103 // StructSigaction is used to silence -Wmissing-field-initializers. 104 using StructSigaction = struct sigaction; 105 #define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction() 106 #else 107 void (*previous_handler)(int); 108 #define FSD_PREVIOUS_INIT SIG_DFL 109 #endif 110 }; 111 112 ABSL_CONST_INIT static FailureSignalData failure_signal_data[] = { 113 {SIGSEGV, "SIGSEGV", FSD_PREVIOUS_INIT}, 114 {SIGILL, "SIGILL", FSD_PREVIOUS_INIT}, 115 {SIGFPE, "SIGFPE", FSD_PREVIOUS_INIT}, 116 {SIGABRT, "SIGABRT", FSD_PREVIOUS_INIT}, 117 {SIGTERM, "SIGTERM", FSD_PREVIOUS_INIT}, 118 #ifndef _WIN32 119 {SIGBUS, "SIGBUS", FSD_PREVIOUS_INIT}, 120 {SIGTRAP, "SIGTRAP", FSD_PREVIOUS_INIT}, 121 #endif 122 }; 123 124 #undef FSD_PREVIOUS_INIT 125 126 static void RaiseToPreviousHandler(int signo) { 127 // Search for the previous handler. 128 for (const auto& it : failure_signal_data) { 129 if (it.signo == signo) { 130 #ifdef ABSL_HAVE_SIGACTION 131 sigaction(signo, &it.previous_action, nullptr); 132 #else 133 signal(signo, it.previous_handler); 134 #endif 135 raise(signo); 136 return; 137 } 138 } 139 140 // Not found, use the default handler. 141 RaiseToDefaultHandler(signo); 142 } 143 144 namespace debugging_internal { 145 146 const char* FailureSignalToString(int signo) { 147 for (const auto& it : failure_signal_data) { 148 if (it.signo == signo) { 149 return it.as_string; 150 } 151 } 152 return ""; 153 } 154 155 } // namespace debugging_internal 156 157 #ifdef ABSL_HAVE_SIGALTSTACK 158 159 static bool SetupAlternateStackOnce() { 160 #if defined(__wasm__) || defined(__asjms__) 161 const size_t page_mask = getpagesize() - 1; 162 #else 163 const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1; 164 #endif 165 size_t stack_size = 166 (std::max(static_cast<size_t>(SIGSTKSZ), size_t{65536}) + page_mask) & 167 ~page_mask; 168 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ 169 defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) 170 // Account for sanitizer instrumentation requiring additional stack space. 171 stack_size *= 5; 172 #endif 173 174 stack_t sigstk; 175 memset(&sigstk, 0, sizeof(sigstk)); 176 sigstk.ss_size = stack_size; 177 178 #ifdef ABSL_HAVE_MMAP 179 #ifndef MAP_STACK 180 #define MAP_STACK 0 181 #endif 182 sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE, 183 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 184 if (sigstk.ss_sp == MAP_FAILED) { 185 ABSL_RAW_LOG(FATAL, "mmap() for alternate signal stack failed"); 186 } 187 #else 188 sigstk.ss_sp = malloc(sigstk.ss_size); 189 if (sigstk.ss_sp == nullptr) { 190 ABSL_RAW_LOG(FATAL, "malloc() for alternate signal stack failed"); 191 } 192 #endif 193 194 if (sigaltstack(&sigstk, nullptr) != 0) { 195 ABSL_RAW_LOG(FATAL, "sigaltstack() failed with errno=%d", errno); 196 } 197 198 #ifdef __linux__ 199 #if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME) 200 // Make a best-effort attempt to name the allocated region in 201 // /proc/$PID/smaps. 202 // 203 // The call to prctl() may fail if the kernel was not configured with the 204 // CONFIG_ANON_VMA_NAME kernel option. This is OK since the call is 205 // primarily a debugging aid. 206 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, sigstk.ss_sp, sigstk.ss_size, 207 "absl-signalstack"); 208 #endif 209 #endif // __linux__ 210 211 return true; 212 } 213 214 #endif 215 216 #ifdef ABSL_HAVE_SIGACTION 217 218 // Sets up an alternate stack for signal handlers once. 219 // Returns the appropriate flag for sig_action.sa_flags 220 // if the system supports using an alternate stack. 221 static int MaybeSetupAlternateStack() { 222 #ifdef ABSL_HAVE_SIGALTSTACK 223 ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce(); 224 return SA_ONSTACK; 225 #else 226 return 0; 227 #endif 228 } 229 230 static void InstallOneFailureHandler(FailureSignalData* data, 231 void (*handler)(int, siginfo_t*, void*)) { 232 struct sigaction act; 233 memset(&act, 0, sizeof(act)); 234 sigemptyset(&act.sa_mask); 235 act.sa_flags |= SA_SIGINFO; 236 // SA_NODEFER is required to handle SIGABRT from 237 // ImmediateAbortSignalHandler(). 238 act.sa_flags |= SA_NODEFER; 239 if (fsh_options.use_alternate_stack) { 240 act.sa_flags |= MaybeSetupAlternateStack(); 241 } 242 act.sa_sigaction = handler; 243 ABSL_RAW_CHECK(sigaction(data->signo, &act, &data->previous_action) == 0, 244 "sigaction() failed"); 245 } 246 247 #else 248 249 static void InstallOneFailureHandler(FailureSignalData* data, 250 void (*handler)(int)) { 251 data->previous_handler = signal(data->signo, handler); 252 ABSL_RAW_CHECK(data->previous_handler != SIG_ERR, "signal() failed"); 253 } 254 255 #endif 256 257 static void WriteSignalMessage(int signo, int cpu, 258 void (*writerfn)(const char*)) { 259 char buf[96]; 260 char on_cpu[32] = {0}; 261 if (cpu != -1) { 262 snprintf(on_cpu, sizeof(on_cpu), " on cpu %d", cpu); 263 } 264 const char* const signal_string = 265 debugging_internal::FailureSignalToString(signo); 266 if (signal_string != nullptr && signal_string[0] != '\0') { 267 snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n", 268 signal_string, 269 static_cast<long>(time(nullptr)), // NOLINT(runtime/int) 270 on_cpu); 271 } else { 272 snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n", 273 signo, static_cast<long>(time(nullptr)), // NOLINT(runtime/int) 274 on_cpu); 275 } 276 writerfn(buf); 277 } 278 279 // `void*` might not be big enough to store `void(*)(const char*)`. 280 struct WriterFnStruct { 281 void (*writerfn)(const char*); 282 }; 283 284 // Many of the absl::debugging_internal::Dump* functions in 285 // examine_stack.h take a writer function pointer that has a void* arg 286 // for historical reasons. failure_signal_handler_writer only takes a 287 // data pointer. This function converts between these types. 288 static void WriterFnWrapper(const char* data, void* arg) { 289 static_cast<WriterFnStruct*>(arg)->writerfn(data); 290 } 291 292 // Convenient wrapper around DumpPCAndFrameSizesAndStackTrace() for signal 293 // handlers. "noinline" so that GetStackFrames() skips the top-most stack 294 // frame for this function. 295 ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace( 296 void* ucontext, bool symbolize_stacktrace, 297 void (*writerfn)(const char*, void*), void* writerfn_arg) { 298 constexpr int kNumStackFrames = 32; 299 void* stack[kNumStackFrames]; 300 int frame_sizes[kNumStackFrames]; 301 int min_dropped_frames; 302 int depth = absl::GetStackFramesWithContext( 303 stack, frame_sizes, kNumStackFrames, 304 1, // Do not include this function in stack trace. 305 ucontext, &min_dropped_frames); 306 absl::debugging_internal::DumpPCAndFrameSizesAndStackTrace( 307 absl::debugging_internal::GetProgramCounter(ucontext), stack, frame_sizes, 308 depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg); 309 } 310 311 // Called by AbslFailureSignalHandler() to write the failure info. It is 312 // called once with writerfn set to WriteToStderr() and then possibly 313 // with writerfn set to the user provided function. 314 static void WriteFailureInfo(int signo, void* ucontext, int cpu, 315 void (*writerfn)(const char*)) { 316 WriterFnStruct writerfn_struct{writerfn}; 317 WriteSignalMessage(signo, cpu, writerfn); 318 WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper, 319 &writerfn_struct); 320 } 321 322 // absl::SleepFor() can't be used here since AbslInternalSleepFor() 323 // may be overridden to do something that isn't async-signal-safe on 324 // some platforms. 325 static void PortableSleepForSeconds(int seconds) { 326 #ifdef _WIN32 327 Sleep(static_cast<DWORD>(seconds * 1000)); 328 #else 329 struct timespec sleep_time; 330 sleep_time.tv_sec = seconds; 331 sleep_time.tv_nsec = 0; 332 while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) { 333 } 334 #endif 335 } 336 337 #ifdef ABSL_HAVE_ALARM 338 // AbslFailureSignalHandler() installs this as a signal handler for 339 // SIGALRM, then sets an alarm to be delivered to the program after a 340 // set amount of time. If AbslFailureSignalHandler() hangs for more than 341 // the alarm timeout, ImmediateAbortSignalHandler() will abort the 342 // program. 343 static void ImmediateAbortSignalHandler(int) { RaiseToDefaultHandler(SIGABRT); } 344 #endif 345 346 // absl::base_internal::GetTID() returns pid_t on most platforms, but 347 // returns absl::base_internal::pid_t on Windows. 348 using GetTidType = decltype(absl::base_internal::GetTID()); 349 ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0); 350 351 static int GetCpuNumber() { 352 #ifdef ABSL_HAVE_SCHED_GETCPU 353 return sched_getcpu(); 354 #elif defined(ABSL_HAVE_PTHREAD_CPU_NUMBER_NP) 355 size_t cpu_num; 356 if (pthread_cpu_number_np(&cpu_num) == 0) { 357 return static_cast<int>(cpu_num); 358 } 359 return -1; 360 #else 361 return -1; 362 #endif 363 } 364 365 #ifndef ABSL_HAVE_SIGACTION 366 static void AbslFailureSignalHandler(int signo) { 367 void* ucontext = nullptr; 368 #else 369 static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) { 370 #endif 371 372 const GetTidType this_tid = absl::base_internal::GetTID(); 373 GetTidType previous_failed_tid = 0; 374 if (!failed_tid.compare_exchange_strong(previous_failed_tid, this_tid, 375 std::memory_order_acq_rel, 376 std::memory_order_relaxed)) { 377 ABSL_RAW_LOG( 378 ERROR, 379 "Signal %d raised at PC=%p while already in AbslFailureSignalHandler()", 380 signo, absl::debugging_internal::GetProgramCounter(ucontext)); 381 if (this_tid != previous_failed_tid) { 382 // Another thread is already in AbslFailureSignalHandler(), so wait 383 // a bit for it to finish. If the other thread doesn't kill us, 384 // we do so after sleeping. 385 PortableSleepForSeconds(3); 386 RaiseToDefaultHandler(signo); 387 // The recursively raised signal may be blocked until we return. 388 return; 389 } 390 } 391 392 // Increase the chance that the CPU we report was the same CPU on which the 393 // signal was received by doing this as early as possible, i.e. after 394 // verifying that this is not a recursive signal handler invocation. 395 int my_cpu = GetCpuNumber(); 396 397 #ifdef ABSL_HAVE_ALARM 398 // Set an alarm to abort the program in case this code hangs or deadlocks. 399 if (fsh_options.alarm_on_failure_secs > 0) { 400 alarm(0); // Cancel any existing alarms. 401 signal(SIGALRM, ImmediateAbortSignalHandler); 402 alarm(static_cast<unsigned int>(fsh_options.alarm_on_failure_secs)); 403 } 404 #endif 405 406 // First write to stderr. 407 WriteFailureInfo( 408 signo, ucontext, my_cpu, +[](const char* data) { 409 absl::raw_log_internal::AsyncSignalSafeWriteError(data, strlen(data)); 410 }); 411 412 // Riskier code (because it is less likely to be async-signal-safe) 413 // goes after this point. 414 if (fsh_options.writerfn != nullptr) { 415 WriteFailureInfo(signo, ucontext, my_cpu, fsh_options.writerfn); 416 fsh_options.writerfn(nullptr); 417 } 418 419 if (fsh_options.call_previous_handler) { 420 RaiseToPreviousHandler(signo); 421 } else { 422 RaiseToDefaultHandler(signo); 423 } 424 } 425 426 void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) { 427 fsh_options = options; 428 for (auto& it : failure_signal_data) { 429 InstallOneFailureHandler(&it, AbslFailureSignalHandler); 430 } 431 } 432 433 ABSL_NAMESPACE_END 434 } // namespace absl