22 #include <sys/types.h> 31 #include <glog/logging.h> 41 namespace symbolizer {
48 class FatalSignalCallbackRegistry {
50 FatalSignalCallbackRegistry();
62 FatalSignalCallbackRegistry::FatalSignalCallbackRegistry()
67 CHECK(!
installed_) <<
"FatalSignalCallbackRegistry::add may not be used " 68 "after installing the signal handlers.";
72 void FatalSignalCallbackRegistry::markInstalled() {
75 <<
"FatalSignalCallbackRegistry::markInstalled must be called " 90 FatalSignalCallbackRegistry* gFatalSignalCallbackRegistry =
91 new FatalSignalCallbackRegistry;
98 {SIGSEGV,
"SIGSEGV", {}},
99 {SIGILL,
"SIGILL", {}},
100 {SIGFPE,
"SIGFPE", {}},
101 {SIGABRT,
"SIGABRT", {}},
102 {SIGBUS,
"SIGBUS", {}},
103 {SIGTERM,
"SIGTERM", {}},
104 {SIGQUIT,
"SIGQUIT", {}},
108 void callPreviousSignalHandler(
int signum) {
112 for (
auto p = kFatalSignals; p->name; ++p) {
113 if (p->number == signum) {
114 sigaction(signum, &p->oldAction,
nullptr);
122 memset(&sa, 0,
sizeof(sa));
123 sa.sa_handler = SIG_DFL;
124 sigaction(signum, &sa,
nullptr);
134 SafeStackTracePrinter* gStackTracePrinter;
142 const char kHexChars[] =
"0123456789abcdef";
147 char*
end = buf +
sizeof(buf);
150 *--p = kHexChars[val & 0x0f];
160 gStackTracePrinter->print(sp);
164 gStackTracePrinter->flush();
167 void dumpTimeInfo() {
172 print(
"*** Aborted at ");
174 print(
" (Unix time, try 'date -d @");
179 const char* sigill_reason(
int si_code) {
182 return "illegal opcode";
184 return "illegal operand";
186 return "illegal addressing mode";
188 return "illegal trap";
190 return "privileged opcode";
192 return "privileged register";
194 return "coprocessor error";
196 return "internal stack error";
203 const char* sigfpe_reason(
int si_code) {
206 return "integer divide by zero";
208 return "integer overflow";
210 return "floating-point divide by zero";
212 return "floating-point overflow";
214 return "floating-point underflow";
216 return "floating-point inexact result";
218 return "floating-point invalid operation";
220 return "subscript out of range";
227 const char* sigsegv_reason(
int si_code) {
230 return "address not mapped to object";
232 return "invalid permissions for mapped object";
239 const char* sigbus_reason(
int si_code) {
242 return "invalid address alignment";
244 return "nonexistent physical address";
246 return "object-specific hardware error";
255 const char* sigtrap_reason(
int si_code) {
258 return "process breakpoint";
260 return "process trace trap";
269 const char* sigchld_reason(
int si_code) {
272 return "child has exited";
274 return "child was killed";
276 return "child terminated abnormally";
278 return "traced child has trapped";
280 return "child has stopped";
282 return "stopped child has continued";
289 const char* sigio_reason(
int si_code) {
292 return "data input available";
294 return "output buffers available";
296 return "input message available";
300 return "high priority input available";
302 return "device disconnected";
309 const char* signal_reason(
int signum,
int si_code) {
312 return sigill_reason(si_code);
314 return sigfpe_reason(si_code);
316 return sigsegv_reason(si_code);
318 return sigbus_reason(si_code);
320 return sigtrap_reason(si_code);
322 return sigchld_reason(si_code);
324 return sigio_reason(si_code);
331 void dumpSignalInfo(
int signum, siginfo_t* siginfo) {
336 const char*
name =
nullptr;
337 for (
auto p = kFatalSignals; p->name; ++p) {
338 if (p->number == signum) {
344 print(
"*** Signal ");
353 printHex(reinterpret_cast<uint64_t>(siginfo->si_addr));
354 print(
") received by PID ");
356 print(
" (pthread TID ");
358 print(
") (linux TID ");
359 printDec(syscall(__NR_gettid));
362 if (siginfo->si_code != SI_KERNEL) {
363 print(
") (maybe from PID ");
364 printDec(siginfo->si_pid);
366 printDec(siginfo->si_uid);
369 auto reason = signal_reason(signum, siginfo->si_code);
371 if (reason !=
nullptr) {
376 print(
"), stack trace: ***\n");
383 constexpr pthread_t kInvalidThreadId = 0;
385 std::atomic<pthread_t> gSignalThread(kInvalidThreadId);
386 std::atomic<bool> gInRecursiveSignalHandler(
false);
389 void innerSignalHandler(
int signum, siginfo_t*
info,
void* ) {
391 pthread_t myId = pthread_self();
393 pthread_t prevSignalThread = kInvalidThreadId;
394 while (!gSignalThread.compare_exchange_strong(prevSignalThread, myId)) {
395 if (pthread_equal(prevSignalThread, myId)) {
399 if (!gInRecursiveSignalHandler.exchange(
true)) {
400 print(
"Entered fatal signal handler recursively. We're in trouble.\n");
401 gStackTracePrinter->printStackTrace(
false);
409 ts.tv_nsec = 100L * 1000 * 1000;
410 nanosleep(&ts,
nullptr);
412 prevSignalThread = kInvalidThreadId;
416 dumpSignalInfo(signum, info);
417 gStackTracePrinter->printStackTrace(
true);
420 gFatalSignalCallbackRegistry->run();
423 void signalHandler(
int signum, siginfo_t* info,
void* uctx) {
424 int savedErrno = errno;
429 innerSignalHandler(signum, info, uctx);
431 gSignalThread = kInvalidThreadId;
433 callPreviousSignalHandler(signum);
439 gFatalSignalCallbackRegistry->add(cb);
443 gFatalSignalCallbackRegistry->markInstalled();
448 std::atomic<bool> gAlreadyInstalled;
453 const size_t kSmallSigAltStackSize = 8931;
455 bool isSmallSigAltStackEnabled() {
457 if (sigaltstack(
nullptr, &ss) != 0) {
460 if ((ss.ss_flags & SS_DISABLE) != 0) {
463 return ss.ss_size <= kSmallSigAltStackSize;
469 if (gAlreadyInstalled.exchange(
true)) {
477 bool useUnsafePrinter = isSmallSigAltStackEnabled();
478 if (useUnsafePrinter) {
485 memset(&sa, 0,
sizeof(sa));
486 if (useUnsafePrinter) {
489 sigfillset(&sa.sa_mask);
491 sigemptyset(&sa.sa_mask);
500 sa.sa_flags |= SA_SIGINFO | SA_ONSTACK;
501 sa.sa_sigaction = &signalHandler;
503 for (
auto p = kFatalSignals; p->name; ++p) {
504 CHECK_ERR(sigaction(p->number, &sa, &p->oldAction));
void addFatalSignalCallback(SignalCallback cb)
uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer)
void installFatalSignalCallbacks()
std::chrono::steady_clock::time_point now()
std::vector< SignalCallback > handlers_
—— Concurrent Priority Queue Implementation ——
std::atomic< bool > installed_
static void run(EventBaseManager *ebm, EventBase *eb, folly::Baton<> *stop, const StringPiece &name)
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
auto end(TestAdlIterable &instance)
struct sigaction oldAction
void installFatalSignalHandler()
Range< const char * > StringPiece
std::chrono::nanoseconds time()