mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Cleans up header order/grouping for consistency: associated header, C/C++ system/standard library headers, library headers, platform-specific #includes. Adds <cstring> where strlen, memcpy are being used: there are a bunch of places we use them transitively. Applies linter-required cleanups. Disables linter on one file due to included RapidJson header. See https://github.com/flutter/flutter/issues/65676 This patch does not cover flutter/shell/platform/darwin. There's a separate, slightly more intensive cleanup for those in progress.
137 lines
3.4 KiB
C++
137 lines
3.4 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/fml/backtrace.h"
|
|
|
|
#include <cxxabi.h>
|
|
#include <dlfcn.h>
|
|
#include <execinfo.h>
|
|
#include <signal.h>
|
|
|
|
#include <sstream>
|
|
|
|
#include "flutter/fml/logging.h"
|
|
|
|
namespace fml {
|
|
|
|
static std::string kKUnknownFrameName = "Unknown";
|
|
|
|
static std::string DemangleSymbolName(const std::string& mangled) {
|
|
if (mangled == kKUnknownFrameName) {
|
|
return kKUnknownFrameName;
|
|
}
|
|
|
|
int status = 0;
|
|
size_t length = 0;
|
|
char* demangled = __cxxabiv1::__cxa_demangle(
|
|
mangled.data(), // mangled name
|
|
nullptr, // output buffer (malloc-ed if nullptr)
|
|
&length, // demangled length
|
|
&status);
|
|
|
|
if (demangled == nullptr || status != 0) {
|
|
return mangled;
|
|
}
|
|
|
|
auto demangled_string = std::string{demangled, length};
|
|
free(demangled);
|
|
return demangled_string;
|
|
}
|
|
|
|
static std::string GetSymbolName(void* symbol) {
|
|
Dl_info info = {};
|
|
|
|
if (::dladdr(symbol, &info) == 0) {
|
|
return kKUnknownFrameName;
|
|
}
|
|
|
|
return DemangleSymbolName({info.dli_sname});
|
|
}
|
|
|
|
std::string BacktraceHere(size_t offset) {
|
|
constexpr size_t kMaxFrames = 256;
|
|
void* symbols[kMaxFrames];
|
|
const auto available_frames = ::backtrace(symbols, kMaxFrames);
|
|
if (available_frames <= 0) {
|
|
return "";
|
|
}
|
|
|
|
std::stringstream stream;
|
|
for (int i = 1 + offset; i < available_frames; ++i) {
|
|
stream << "Frame " << i - 1 - offset << ": " << symbols[i] << " "
|
|
<< GetSymbolName(symbols[i]) << std::endl;
|
|
}
|
|
return stream.str();
|
|
}
|
|
|
|
static size_t kKnownSignalHandlers[] = {
|
|
SIGABRT, // abort program
|
|
SIGFPE, // floating-point exception
|
|
SIGBUS, // bus error
|
|
SIGSEGV, // segmentation violation
|
|
SIGSYS, // non-existent system call invoked
|
|
SIGPIPE, // write on a pipe with no reader
|
|
SIGALRM, // real-time timer expired
|
|
SIGTERM, // software termination signal
|
|
};
|
|
|
|
static std::string SignalNameToString(int signal) {
|
|
switch (signal) {
|
|
case SIGABRT:
|
|
return "SIGABRT";
|
|
case SIGFPE:
|
|
return "SIGFPE";
|
|
case SIGBUS:
|
|
return "SIGBUS";
|
|
case SIGSEGV:
|
|
return "SIGSEGV";
|
|
case SIGSYS:
|
|
return "SIGSYS";
|
|
case SIGPIPE:
|
|
return "SIGPIPE";
|
|
case SIGALRM:
|
|
return "SIGALRM";
|
|
case SIGTERM:
|
|
return "SIGTERM";
|
|
};
|
|
return std::to_string(signal);
|
|
}
|
|
|
|
static void ToggleSignalHandlers(bool set);
|
|
|
|
static void SignalHandler(int signal) {
|
|
// We are a crash signal handler. This can only happen once. Since we don't
|
|
// want to catch crashes while we are generating the crash reports, disable
|
|
// all set signal handlers to their default values before reporting the crash
|
|
// and re-raising the signal.
|
|
ToggleSignalHandlers(false);
|
|
|
|
FML_LOG(ERROR) << "Caught signal " << SignalNameToString(signal)
|
|
<< " during program execution." << std::endl
|
|
<< BacktraceHere(3);
|
|
|
|
::raise(signal);
|
|
}
|
|
|
|
static void ToggleSignalHandlers(bool set) {
|
|
for (size_t i = 0; i < sizeof(kKnownSignalHandlers) / sizeof(size_t); ++i) {
|
|
auto signal_name = kKnownSignalHandlers[i];
|
|
auto handler = set ? &SignalHandler : SIG_DFL;
|
|
|
|
if (::signal(signal_name, handler) == SIG_ERR) {
|
|
FML_LOG(ERROR) << "Could not attach signal handler for " << signal_name;
|
|
}
|
|
}
|
|
}
|
|
|
|
void InstallCrashHandler() {
|
|
ToggleSignalHandlers(true);
|
|
}
|
|
|
|
bool IsCrashHandlingSupported() {
|
|
return true;
|
|
}
|
|
|
|
} // namespace fml
|