failure_signal_handler.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. #include "absl/debugging/failure_signal_handler.h"
  17. #include "absl/base/config.h"
  18. #ifdef _WIN32
  19. #include <windows.h>
  20. #else
  21. #include <sched.h>
  22. #include <unistd.h>
  23. #endif
  24. #ifdef __APPLE__
  25. #include <TargetConditionals.h>
  26. #endif
  27. #ifdef ABSL_HAVE_MMAP
  28. #include <sys/mman.h>
  29. #endif
  30. #include <algorithm>
  31. #include <atomic>
  32. #include <cerrno>
  33. #include <csignal>
  34. #include <cstdio>
  35. #include <cstring>
  36. #include <ctime>
  37. #include "absl/base/attributes.h"
  38. #include "absl/base/internal/errno_saver.h"
  39. #include "absl/base/internal/raw_logging.h"
  40. #include "absl/base/internal/sysinfo.h"
  41. #include "absl/debugging/internal/examine_stack.h"
  42. #include "absl/debugging/stacktrace.h"
  43. #ifndef _WIN32
  44. #define ABSL_HAVE_SIGACTION
  45. // Apple WatchOS and TVOS don't allow sigaltstack
  46. #if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
  47. !(defined(TARGET_OS_TV) && TARGET_OS_TV)
  48. #define ABSL_HAVE_SIGALTSTACK
  49. #endif
  50. #endif
  51. namespace absl {
  52. ABSL_NAMESPACE_BEGIN
  53. ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options;
  54. // Resets the signal handler for signo to the default action for that
  55. // signal, then raises the signal.
  56. static void RaiseToDefaultHandler(int signo) {
  57. signal(signo, SIG_DFL);
  58. raise(signo);
  59. }
  60. struct FailureSignalData {
  61. const int signo;
  62. const char* const as_string;
  63. #ifdef ABSL_HAVE_SIGACTION
  64. struct sigaction previous_action;
  65. // StructSigaction is used to silence -Wmissing-field-initializers.
  66. using StructSigaction = struct sigaction;
  67. #define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
  68. #else
  69. void (*previous_handler)(int);
  70. #define FSD_PREVIOUS_INIT SIG_DFL
  71. #endif
  72. };
  73. ABSL_CONST_INIT static FailureSignalData failure_signal_data[] = {
  74. {SIGSEGV, "SIGSEGV", FSD_PREVIOUS_INIT},
  75. {SIGILL, "SIGILL", FSD_PREVIOUS_INIT},
  76. {SIGFPE, "SIGFPE", FSD_PREVIOUS_INIT},
  77. {SIGABRT, "SIGABRT", FSD_PREVIOUS_INIT},
  78. {SIGTERM, "SIGTERM", FSD_PREVIOUS_INIT},
  79. #ifndef _WIN32
  80. {SIGBUS, "SIGBUS", FSD_PREVIOUS_INIT},
  81. {SIGTRAP, "SIGTRAP", FSD_PREVIOUS_INIT},
  82. #endif
  83. };
  84. #undef FSD_PREVIOUS_INIT
  85. static void RaiseToPreviousHandler(int signo) {
  86. // Search for the previous handler.
  87. for (const auto& it : failure_signal_data) {
  88. if (it.signo == signo) {
  89. #ifdef ABSL_HAVE_SIGACTION
  90. sigaction(signo, &it.previous_action, nullptr);
  91. #else
  92. signal(signo, it.previous_handler);
  93. #endif
  94. raise(signo);
  95. return;
  96. }
  97. }
  98. // Not found, use the default handler.
  99. RaiseToDefaultHandler(signo);
  100. }
  101. namespace debugging_internal {
  102. const char* FailureSignalToString(int signo) {
  103. for (const auto& it : failure_signal_data) {
  104. if (it.signo == signo) {
  105. return it.as_string;
  106. }
  107. }
  108. return "";
  109. }
  110. } // namespace debugging_internal
  111. #ifdef ABSL_HAVE_SIGALTSTACK
  112. static bool SetupAlternateStackOnce() {
  113. #if defined(__wasm__) || defined (__asjms__)
  114. const size_t page_mask = getpagesize() - 1;
  115. #else
  116. const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
  117. #endif
  118. size_t stack_size =
  119. (std::max<size_t>(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
  120. #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
  121. defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
  122. // Account for sanitizer instrumentation requiring additional stack space.
  123. stack_size *= 5;
  124. #endif
  125. stack_t sigstk;
  126. memset(&sigstk, 0, sizeof(sigstk));
  127. sigstk.ss_size = stack_size;
  128. #ifdef ABSL_HAVE_MMAP
  129. #ifndef MAP_STACK
  130. #define MAP_STACK 0
  131. #endif
  132. #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
  133. #define MAP_ANONYMOUS MAP_ANON
  134. #endif
  135. sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE,
  136. MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
  137. if (sigstk.ss_sp == MAP_FAILED) {
  138. ABSL_RAW_LOG(FATAL, "mmap() for alternate signal stack failed");
  139. }
  140. #else
  141. sigstk.ss_sp = malloc(sigstk.ss_size);
  142. if (sigstk.ss_sp == nullptr) {
  143. ABSL_RAW_LOG(FATAL, "malloc() for alternate signal stack failed");
  144. }
  145. #endif
  146. if (sigaltstack(&sigstk, nullptr) != 0) {
  147. ABSL_RAW_LOG(FATAL, "sigaltstack() failed with errno=%d", errno);
  148. }
  149. return true;
  150. }
  151. #endif
  152. #ifdef ABSL_HAVE_SIGACTION
  153. // Sets up an alternate stack for signal handlers once.
  154. // Returns the appropriate flag for sig_action.sa_flags
  155. // if the system supports using an alternate stack.
  156. static int MaybeSetupAlternateStack() {
  157. #ifdef ABSL_HAVE_SIGALTSTACK
  158. ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce();
  159. return SA_ONSTACK;
  160. #else
  161. return 0;
  162. #endif
  163. }
  164. static void InstallOneFailureHandler(FailureSignalData* data,
  165. void (*handler)(int, siginfo_t*, void*)) {
  166. struct sigaction act;
  167. memset(&act, 0, sizeof(act));
  168. sigemptyset(&act.sa_mask);
  169. act.sa_flags |= SA_SIGINFO;
  170. // SA_NODEFER is required to handle SIGABRT from
  171. // ImmediateAbortSignalHandler().
  172. act.sa_flags |= SA_NODEFER;
  173. if (fsh_options.use_alternate_stack) {
  174. act.sa_flags |= MaybeSetupAlternateStack();
  175. }
  176. act.sa_sigaction = handler;
  177. ABSL_RAW_CHECK(sigaction(data->signo, &act, &data->previous_action) == 0,
  178. "sigaction() failed");
  179. }
  180. #else
  181. static void InstallOneFailureHandler(FailureSignalData* data,
  182. void (*handler)(int)) {
  183. data->previous_handler = signal(data->signo, handler);
  184. ABSL_RAW_CHECK(data->previous_handler != SIG_ERR, "signal() failed");
  185. }
  186. #endif
  187. static void WriteToStderr(const char* data) {
  188. absl::base_internal::ErrnoSaver errno_saver;
  189. absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
  190. }
  191. static void WriteSignalMessage(int signo, int cpu,
  192. void (*writerfn)(const char*)) {
  193. char buf[96];
  194. char on_cpu[32] = {0};
  195. if (cpu != -1) {
  196. snprintf(on_cpu, sizeof(on_cpu), " on cpu %d", cpu);
  197. }
  198. const char* const signal_string =
  199. debugging_internal::FailureSignalToString(signo);
  200. if (signal_string != nullptr && signal_string[0] != '\0') {
  201. snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n",
  202. signal_string,
  203. static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
  204. on_cpu);
  205. } else {
  206. snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
  207. signo, static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
  208. on_cpu);
  209. }
  210. writerfn(buf);
  211. }
  212. // `void*` might not be big enough to store `void(*)(const char*)`.
  213. struct WriterFnStruct {
  214. void (*writerfn)(const char*);
  215. };
  216. // Many of the absl::debugging_internal::Dump* functions in
  217. // examine_stack.h take a writer function pointer that has a void* arg
  218. // for historical reasons. failure_signal_handler_writer only takes a
  219. // data pointer. This function converts between these types.
  220. static void WriterFnWrapper(const char* data, void* arg) {
  221. static_cast<WriterFnStruct*>(arg)->writerfn(data);
  222. }
  223. // Convenient wrapper around DumpPCAndFrameSizesAndStackTrace() for signal
  224. // handlers. "noinline" so that GetStackFrames() skips the top-most stack
  225. // frame for this function.
  226. ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace(
  227. void* ucontext, bool symbolize_stacktrace,
  228. void (*writerfn)(const char*, void*), void* writerfn_arg) {
  229. constexpr int kNumStackFrames = 32;
  230. void* stack[kNumStackFrames];
  231. int frame_sizes[kNumStackFrames];
  232. int min_dropped_frames;
  233. int depth = absl::GetStackFramesWithContext(
  234. stack, frame_sizes, kNumStackFrames,
  235. 1, // Do not include this function in stack trace.
  236. ucontext, &min_dropped_frames);
  237. absl::debugging_internal::DumpPCAndFrameSizesAndStackTrace(
  238. absl::debugging_internal::GetProgramCounter(ucontext), stack, frame_sizes,
  239. depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg);
  240. }
  241. // Called by AbslFailureSignalHandler() to write the failure info. It is
  242. // called once with writerfn set to WriteToStderr() and then possibly
  243. // with writerfn set to the user provided function.
  244. static void WriteFailureInfo(int signo, void* ucontext, int cpu,
  245. void (*writerfn)(const char*)) {
  246. WriterFnStruct writerfn_struct{writerfn};
  247. WriteSignalMessage(signo, cpu, writerfn);
  248. WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,
  249. &writerfn_struct);
  250. }
  251. // absl::SleepFor() can't be used here since AbslInternalSleepFor()
  252. // may be overridden to do something that isn't async-signal-safe on
  253. // some platforms.
  254. static void PortableSleepForSeconds(int seconds) {
  255. #ifdef _WIN32
  256. Sleep(seconds * 1000);
  257. #else
  258. struct timespec sleep_time;
  259. sleep_time.tv_sec = seconds;
  260. sleep_time.tv_nsec = 0;
  261. while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {}
  262. #endif
  263. }
  264. #ifdef ABSL_HAVE_ALARM
  265. // AbslFailureSignalHandler() installs this as a signal handler for
  266. // SIGALRM, then sets an alarm to be delivered to the program after a
  267. // set amount of time. If AbslFailureSignalHandler() hangs for more than
  268. // the alarm timeout, ImmediateAbortSignalHandler() will abort the
  269. // program.
  270. static void ImmediateAbortSignalHandler(int) {
  271. RaiseToDefaultHandler(SIGABRT);
  272. }
  273. #endif
  274. // absl::base_internal::GetTID() returns pid_t on most platforms, but
  275. // returns absl::base_internal::pid_t on Windows.
  276. using GetTidType = decltype(absl::base_internal::GetTID());
  277. ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0);
  278. #ifndef ABSL_HAVE_SIGACTION
  279. static void AbslFailureSignalHandler(int signo) {
  280. void* ucontext = nullptr;
  281. #else
  282. static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
  283. #endif
  284. const GetTidType this_tid = absl::base_internal::GetTID();
  285. GetTidType previous_failed_tid = 0;
  286. if (!failed_tid.compare_exchange_strong(
  287. previous_failed_tid, static_cast<intptr_t>(this_tid),
  288. std::memory_order_acq_rel, std::memory_order_relaxed)) {
  289. ABSL_RAW_LOG(
  290. ERROR,
  291. "Signal %d raised at PC=%p while already in AbslFailureSignalHandler()",
  292. signo, absl::debugging_internal::GetProgramCounter(ucontext));
  293. if (this_tid != previous_failed_tid) {
  294. // Another thread is already in AbslFailureSignalHandler(), so wait
  295. // a bit for it to finish. If the other thread doesn't kill us,
  296. // we do so after sleeping.
  297. PortableSleepForSeconds(3);
  298. RaiseToDefaultHandler(signo);
  299. // The recursively raised signal may be blocked until we return.
  300. return;
  301. }
  302. }
  303. // Increase the chance that the CPU we report was the same CPU on which the
  304. // signal was received by doing this as early as possible, i.e. after
  305. // verifying that this is not a recursive signal handler invocation.
  306. int my_cpu = -1;
  307. #ifdef ABSL_HAVE_SCHED_GETCPU
  308. my_cpu = sched_getcpu();
  309. #endif
  310. #ifdef ABSL_HAVE_ALARM
  311. // Set an alarm to abort the program in case this code hangs or deadlocks.
  312. if (fsh_options.alarm_on_failure_secs > 0) {
  313. alarm(0); // Cancel any existing alarms.
  314. signal(SIGALRM, ImmediateAbortSignalHandler);
  315. alarm(fsh_options.alarm_on_failure_secs);
  316. }
  317. #endif
  318. // First write to stderr.
  319. WriteFailureInfo(signo, ucontext, my_cpu, WriteToStderr);
  320. // Riskier code (because it is less likely to be async-signal-safe)
  321. // goes after this point.
  322. if (fsh_options.writerfn != nullptr) {
  323. WriteFailureInfo(signo, ucontext, my_cpu, fsh_options.writerfn);
  324. fsh_options.writerfn(nullptr);
  325. }
  326. if (fsh_options.call_previous_handler) {
  327. RaiseToPreviousHandler(signo);
  328. } else {
  329. RaiseToDefaultHandler(signo);
  330. }
  331. }
  332. void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) {
  333. fsh_options = options;
  334. for (auto& it : failure_signal_data) {
  335. InstallOneFailureHandler(&it, AbslFailureSignalHandler);
  336. }
  337. }
  338. ABSL_NAMESPACE_END
  339. } // namespace absl