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 #include "flutter/fml/paths.h"
21 #include "third_party/abseil-cpp/absl/debugging/symbolize.h"
22 
23 namespace fml {
24 
25 static std::string kKUnknownFrameName = "Unknown";
26 
27 static std::string DemangleSymbolName(const std::string& mangled) {
28  if (mangled == kKUnknownFrameName) {
29  return kKUnknownFrameName;
30  }
31 
32  int status = 0;
33  size_t length = 0;
34  char* demangled = __cxxabiv1::__cxa_demangle(
35  mangled.data(), // mangled name
36  nullptr, // output buffer (malloc-ed if nullptr)
37  &length, // demangled length
38  &status);
39 
40  if (demangled == nullptr || status != 0) {
41  return mangled;
42  }
43 
44  auto demangled_string = std::string{demangled, length};
45  free(demangled);
46  return demangled_string;
47 }
48 
49 static std::string GetSymbolName(void* symbol) {
50  char name[1024];
51  if (!absl::Symbolize(symbol, name, sizeof(name))) {
52  return kKUnknownFrameName;
53  }
54 
55  return DemangleSymbolName({name});
56 }
57 
58 std::string BacktraceHere(size_t offset) {
59  constexpr size_t kMaxFrames = 256;
60  void* symbols[kMaxFrames];
61  const auto available_frames = ::backtrace(symbols, kMaxFrames);
62  if (available_frames <= 0) {
63  return "";
64  }
65 
66  std::stringstream stream;
67  for (int i = 1 + offset; i < available_frames; ++i) {
68  stream << "Frame " << i - 1 - offset << ": " << symbols[i] << " "
69  << GetSymbolName(symbols[i]) << std::endl;
70  }
71  return stream.str();
72 }
73 
74 static size_t kKnownSignalHandlers[] = {
75  SIGABRT, // abort program
76  SIGFPE, // floating-point exception
77  SIGBUS, // bus error
78  SIGSEGV, // segmentation violation
79  SIGSYS, // non-existent system call invoked
80  SIGPIPE, // write on a pipe with no reader
81  SIGALRM, // real-time timer expired
82  SIGTERM, // software termination signal
83 };
84 
85 static std::string SignalNameToString(int signal) {
86  switch (signal) {
87  case SIGABRT:
88  return "SIGABRT";
89  case SIGFPE:
90  return "SIGFPE";
91  case SIGBUS:
92  return "SIGBUS";
93  case SIGSEGV:
94  return "SIGSEGV";
95  case SIGSYS:
96  return "SIGSYS";
97  case SIGPIPE:
98  return "SIGPIPE";
99  case SIGALRM:
100  return "SIGALRM";
101  case SIGTERM:
102  return "SIGTERM";
103  };
104  return std::to_string(signal);
105 }
106 
107 static void ToggleSignalHandlers(bool set);
108 
109 static void SignalHandler(int signal) {
110  // We are a crash signal handler. This can only happen once. Since we don't
111  // want to catch crashes while we are generating the crash reports, disable
112  // all set signal handlers to their default values before reporting the crash
113  // and re-raising the signal.
114  ToggleSignalHandlers(false);
115 
116  FML_LOG(ERROR) << "Caught signal " << SignalNameToString(signal)
117  << " during program execution." << std::endl
118  << BacktraceHere(3);
119 
120  ::raise(signal);
121 }
122 
123 static void ToggleSignalHandlers(bool set) {
124  for (size_t i = 0; i < sizeof(kKnownSignalHandlers) / sizeof(size_t); ++i) {
125  auto signal_name = kKnownSignalHandlers[i];
126  auto handler = set ? &SignalHandler : SIG_DFL;
127 
128  if (::signal(signal_name, handler) == SIG_ERR) {
129  FML_LOG(ERROR) << "Could not attach signal handler for " << signal_name;
130  }
131  }
132 }
133 
135 #if OS_WIN
136  if (!IsDebuggerPresent()) {
137  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
138  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
139  }
140 #endif
141  auto exe_path = fml::paths::GetExecutablePath();
142  if (exe_path.first) {
143  absl::InitializeSymbolizer(exe_path.second.c_str());
144  }
145  ToggleSignalHandlers(true);
146 }
147 
149  return true;
150 }
151 
152 } // namespace fml
void InstallCrashHandler()
Definition: backtrace.cc:134
static std::string DemangleSymbolName(const std::string &mangled)
Definition: backtrace.cc:27
static std::string kKUnknownFrameName
Definition: backtrace.cc:25
bool IsCrashHandlingSupported()
Definition: backtrace.cc:148
std::string BacktraceHere(size_t offset)
Definition: backtrace.cc:58
#define FML_LOG(severity)
Definition: logging.h:65
static void SignalHandler(int signal)
Definition: backtrace.cc:109
Definition: ascii_trie.cc:9
static void ToggleSignalHandlers(bool set)
Definition: backtrace.cc:123
static std::string GetSymbolName(void *symbol)
Definition: backtrace.cc:49
size_t length
static std::string SignalNameToString(int signal)
Definition: backtrace.cc:85
static size_t kKnownSignalHandlers[]
Definition: backtrace.cc:74
const char * name
Definition: fuchsia.cc:50
std::pair< bool, std::string > GetExecutablePath()