Flutter Engine
backtrace.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/fml/backtrace.h"
6 
7 #include <cxxabi.h>
8 #include <dlfcn.h>
9 #include <execinfo.h>
10 
11 #include <csignal>
12 #include <sstream>
13 
14 #if OS_WIN
15 #include <crtdbg.h>
16 #include <debugapi.h>
17 #endif
18 
19 #include "flutter/fml/logging.h"
20 
21 namespace fml {
22 
23 static std::string kKUnknownFrameName = "Unknown";
24 
25 static std::string DemangleSymbolName(const std::string& mangled) {
26  if (mangled == kKUnknownFrameName) {
27  return kKUnknownFrameName;
28  }
29 
30  int status = 0;
31  size_t length = 0;
32  char* demangled = __cxxabiv1::__cxa_demangle(
33  mangled.data(), // mangled name
34  nullptr, // output buffer (malloc-ed if nullptr)
35  &length, // demangled length
36  &status);
37 
38  if (demangled == nullptr || status != 0) {
39  return mangled;
40  }
41 
42  auto demangled_string = std::string{demangled, length};
43  free(demangled);
44  return demangled_string;
45 }
46 
47 static std::string GetSymbolName(void* symbol) {
48  Dl_info info = {};
49 
50  if (::dladdr(symbol, &info) == 0) {
51  return kKUnknownFrameName;
52  }
53 
54  return DemangleSymbolName({info.dli_sname});
55 }
56 
57 std::string BacktraceHere(size_t offset) {
58  constexpr size_t kMaxFrames = 256;
59  void* symbols[kMaxFrames];
60  const auto available_frames = ::backtrace(symbols, kMaxFrames);
61  if (available_frames <= 0) {
62  return "";
63  }
64 
65  std::stringstream stream;
66  for (int i = 1 + offset; i < available_frames; ++i) {
67  stream << "Frame " << i - 1 - offset << ": " << symbols[i] << " "
68  << GetSymbolName(symbols[i]) << std::endl;
69  }
70  return stream.str();
71 }
72 
73 static size_t kKnownSignalHandlers[] = {
74  SIGABRT, // abort program
75  SIGFPE, // floating-point exception
76  SIGBUS, // bus error
77  SIGSEGV, // segmentation violation
78  SIGSYS, // non-existent system call invoked
79  SIGPIPE, // write on a pipe with no reader
80  SIGALRM, // real-time timer expired
81  SIGTERM, // software termination signal
82 };
83 
84 static std::string SignalNameToString(int signal) {
85  switch (signal) {
86  case SIGABRT:
87  return "SIGABRT";
88  case SIGFPE:
89  return "SIGFPE";
90  case SIGBUS:
91  return "SIGBUS";
92  case SIGSEGV:
93  return "SIGSEGV";
94  case SIGSYS:
95  return "SIGSYS";
96  case SIGPIPE:
97  return "SIGPIPE";
98  case SIGALRM:
99  return "SIGALRM";
100  case SIGTERM:
101  return "SIGTERM";
102  };
103  return std::to_string(signal);
104 }
105 
106 static void ToggleSignalHandlers(bool set);
107 
108 static void SignalHandler(int signal) {
109  // We are a crash signal handler. This can only happen once. Since we don't
110  // want to catch crashes while we are generating the crash reports, disable
111  // all set signal handlers to their default values before reporting the crash
112  // and re-raising the signal.
113  ToggleSignalHandlers(false);
114 
115  FML_LOG(ERROR) << "Caught signal " << SignalNameToString(signal)
116  << " during program execution." << std::endl
117  << BacktraceHere(3);
118 
119  ::raise(signal);
120 }
121 
122 static void ToggleSignalHandlers(bool set) {
123  for (size_t i = 0; i < sizeof(kKnownSignalHandlers) / sizeof(size_t); ++i) {
124  auto signal_name = kKnownSignalHandlers[i];
125  auto handler = set ? &SignalHandler : SIG_DFL;
126 
127  if (::signal(signal_name, handler) == SIG_ERR) {
128  FML_LOG(ERROR) << "Could not attach signal handler for " << signal_name;
129  }
130  }
131 }
132 
134 #if OS_WIN
135  if (!IsDebuggerPresent()) {
136  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
137  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
138  }
139 #endif
140  ToggleSignalHandlers(true);
141 }
142 
144  return true;
145 }
146 
147 } // namespace fml
void InstallCrashHandler()
Definition: backtrace.cc:133
static std::string DemangleSymbolName(const std::string &mangled)
Definition: backtrace.cc:25
static std::string kKUnknownFrameName
Definition: backtrace.cc:23
bool IsCrashHandlingSupported()
Definition: backtrace.cc:143
std::string BacktraceHere(size_t offset)
Definition: backtrace.cc:57
#define FML_LOG(severity)
Definition: logging.h:65
static void SignalHandler(int signal)
Definition: backtrace.cc:108
Definition: ascii_trie.cc:9
size_t length
static void ToggleSignalHandlers(bool set)
Definition: backtrace.cc:122
static std::string GetSymbolName(void *symbol)
Definition: backtrace.cc:47
static std::string SignalNameToString(int signal)
Definition: backtrace.cc:84
static size_t kKnownSignalHandlers[]
Definition: backtrace.cc:73