This commit is contained in:
Ivan Blinkov 2020-05-30 00:36:47 +03:00
parent 69dedcbe21
commit f88b85625a
2 changed files with 61 additions and 62 deletions

View File

@ -3,35 +3,38 @@
#include <Poco/File.h> #include <Poco/File.h>
#include <Poco/Util/Application.h> #include <Poco/Util/Application.h>
#include <Common/config.h>
#include <common/getFQDNOrHostName.h> #include <common/getFQDNOrHostName.h>
#include <common/logger_useful.h> #include <common/logger_useful.h>
#if !defined(ARCADIA_BUILD) #if !defined(ARCADIA_BUILD)
# include "Common/config_version.h" # include "Common/config_version.h"
# include <Common/config.h>
#endif #endif
#if USE_SENTRY #if USE_SENTRY
#include <sentry.h> # include <sentry.h>
#endif #endif
namespace { namespace
static bool initialized = false; {
static bool initialized = false;
void setExtras() { void setExtras()
{
#if USE_SENTRY #if USE_SENTRY
sentry_set_extra("version_githash", sentry_value_new_string(VERSION_GITHASH)); sentry_set_extra("version_githash", sentry_value_new_string(VERSION_GITHASH));
sentry_set_extra("version_describe", sentry_value_new_string(VERSION_DESCRIBE)); sentry_set_extra("version_describe", sentry_value_new_string(VERSION_DESCRIBE));
sentry_set_extra("version_integer", sentry_value_new_int32(VERSION_INTEGER)); sentry_set_extra("version_integer", sentry_value_new_int32(VERSION_INTEGER));
sentry_set_extra("version_revision", sentry_value_new_int32(VERSION_REVISION)); sentry_set_extra("version_revision", sentry_value_new_int32(VERSION_REVISION));
sentry_set_extra("version_major", sentry_value_new_int32(VERSION_MAJOR)); sentry_set_extra("version_major", sentry_value_new_int32(VERSION_MAJOR));
sentry_set_extra("version_minor", sentry_value_new_int32(VERSION_MINOR)); sentry_set_extra("version_minor", sentry_value_new_int32(VERSION_MINOR));
sentry_set_extra("version_patch", sentry_value_new_int32(VERSION_PATCH)); sentry_set_extra("version_patch", sentry_value_new_int32(VERSION_PATCH));
#endif #endif
} }
} }
void SentryWriter::initialize(Poco::Util::LayeredConfiguration & config) { void SentryWriter::initialize(Poco::Util::LayeredConfiguration & config)
{
#if USE_SENTRY #if USE_SENTRY
bool enabled = false; bool enabled = false;
bool debug = config.getBool("send_crash_reports.debug", false); bool debug = config.getBool("send_crash_reports.debug", false);
@ -44,14 +47,10 @@ void SentryWriter::initialize(Poco::Util::LayeredConfiguration & config) {
} }
if (enabled) if (enabled)
{ {
const std::string & endpoint = config.getString( const std::string & endpoint
"send_crash_reports.endpoint", = config.getString("send_crash_reports.endpoint", "https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277");
"https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277" const std::string & temp_folder_path
); = config.getString("send_crash_reports.tmp_path", config.getString("tmp_path", Poco::Path::temp()) + "sentry/");
const std::string & temp_folder_path = config.getString(
"send_crash_reports.tmp_path",
config.getString("tmp_path", Poco::Path::temp()) + "sentry/"
);
Poco::File(temp_folder_path).createDirectories(); Poco::File(temp_folder_path).createDirectories();
sentry_options_t * options = sentry_options_new(); sentry_options_t * options = sentry_options_new();
@ -62,9 +61,12 @@ void SentryWriter::initialize(Poco::Util::LayeredConfiguration & config) {
} }
sentry_options_set_dsn(options, endpoint.c_str()); sentry_options_set_dsn(options, endpoint.c_str());
sentry_options_set_database_path(options, temp_folder_path.c_str()); sentry_options_set_database_path(options, temp_folder_path.c_str());
if (strstr(VERSION_DESCRIBE, "-stable") || strstr(VERSION_DESCRIBE, "-lts")) { if (strstr(VERSION_DESCRIBE, "-stable") || strstr(VERSION_DESCRIBE, "-lts"))
{
sentry_options_set_environment(options, "prod"); sentry_options_set_environment(options, "prod");
} else { }
else
{
sentry_options_set_environment(options, "test"); sentry_options_set_environment(options, "test");
} }
int init_status = sentry_init(options); int init_status = sentry_init(options);
@ -75,14 +77,12 @@ void SentryWriter::initialize(Poco::Util::LayeredConfiguration & config) {
&Logger::get("SentryWriter"), &Logger::get("SentryWriter"),
"Sending crash reports is initialized with {} endpoint and {} temp folder", "Sending crash reports is initialized with {} endpoint and {} temp folder",
endpoint, endpoint,
temp_folder_path temp_folder_path);
);
} }
else else
{ {
LOG_WARNING(&Logger::get("SentryWriter"), "Sending crash reports failed to initialized with {} status", init_status); LOG_WARNING(&Logger::get("SentryWriter"), "Sending crash reports failed to initialized with {} status", init_status);
} }
} }
else else
{ {
@ -91,20 +91,17 @@ void SentryWriter::initialize(Poco::Util::LayeredConfiguration & config) {
#endif #endif
} }
void SentryWriter::shutdown() { void SentryWriter::shutdown()
{
#if USE_SENTRY #if USE_SENTRY
if (initialized) { if (initialized)
{
sentry_shutdown(); sentry_shutdown();
} }
#endif #endif
} }
void SentryWriter::onFault( void SentryWriter::onFault(int sig, const siginfo_t & info, const ucontext_t & context, const StackTrace & stack_trace)
int sig,
const siginfo_t & info,
const ucontext_t & context,
const StackTrace & stack_trace
)
{ {
#if USE_SENTRY #if USE_SENTRY
if (initialized) if (initialized)
@ -178,4 +175,4 @@ void SentryWriter::onFault(
LOG_INFO(&Logger::get("SentryWriter"), "Not sending crash report"); LOG_INFO(&Logger::get("SentryWriter"), "Not sending crash report");
} }
#endif #endif
} }

View File

@ -1,12 +1,12 @@
#include <Common/StackTrace.h> #include <Common/StackTrace.h>
#include <Core/Defines.h>
#include <Common/Dwarf.h> #include <Common/Dwarf.h>
#include <Common/Elf.h> #include <Common/Elf.h>
#include <Common/SymbolIndex.h>
#include <Common/MemorySanitizer.h> #include <Common/MemorySanitizer.h>
#include <Common/SymbolIndex.h>
#include <common/SimpleCache.h> #include <common/SimpleCache.h>
#include <common/demangle.h> #include <common/demangle.h>
#include <Core/Defines.h>
#include <cstring> #include <cstring>
#include <filesystem> #include <filesystem>
@ -26,8 +26,7 @@ std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext
std::stringstream error; std::stringstream error;
switch (sig) switch (sig)
{ {
case SIGSEGV: case SIGSEGV: {
{
/// Print info about address and reason. /// Print info about address and reason.
if (nullptr == info.si_addr) if (nullptr == info.si_addr)
error << "Address: NULL pointer."; error << "Address: NULL pointer.";
@ -59,8 +58,7 @@ std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext
break; break;
} }
case SIGBUS: case SIGBUS: {
{
switch (info.si_code) switch (info.si_code)
{ {
case BUS_ADRALN: case BUS_ADRALN:
@ -92,8 +90,7 @@ std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext
break; break;
} }
case SIGILL: case SIGILL: {
{
switch (info.si_code) switch (info.si_code)
{ {
case ILL_ILLOPC: case ILL_ILLOPC:
@ -127,8 +124,7 @@ std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext
break; break;
} }
case SIGFPE: case SIGFPE: {
{
switch (info.si_code) switch (info.si_code)
{ {
case FPE_INTDIV: case FPE_INTDIV:
@ -162,8 +158,7 @@ std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext
break; break;
} }
case SIGTSTP: case SIGTSTP: {
{
error << "This is a signal used for debugging purposes by the user."; error << "This is a signal used for debugging purposes by the user.";
break; break;
} }
@ -176,13 +171,13 @@ static void * getCallerAddress(const ucontext_t & context)
{ {
#if defined(__x86_64__) #if defined(__x86_64__)
/// Get the address at the time the signal was raised from the RIP (x86-64) /// Get the address at the time the signal was raised from the RIP (x86-64)
#if defined(__FreeBSD__) # if defined(__FreeBSD__)
return reinterpret_cast<void *>(context.uc_mcontext.mc_rip); return reinterpret_cast<void *>(context.uc_mcontext.mc_rip);
#elif defined(__APPLE__) # elif defined(__APPLE__)
return reinterpret_cast<void *>(context.uc_mcontext->__ss.__rip); return reinterpret_cast<void *>(context.uc_mcontext->__ss.__rip);
#else # else
return reinterpret_cast<void *>(context.uc_mcontext.gregs[REG_RIP]); return reinterpret_cast<void *>(context.uc_mcontext.gregs[REG_RIP]);
#endif # endif
#elif defined(__aarch64__) #elif defined(__aarch64__)
return reinterpret_cast<void *>(context.uc_mcontext.pc); return reinterpret_cast<void *>(context.uc_mcontext.pc);
#else #else
@ -197,7 +192,8 @@ static void symbolize(const void * const * frame_pointers, size_t offset, size_t
const DB::SymbolIndex & symbol_index = DB::SymbolIndex::instance(); const DB::SymbolIndex & symbol_index = DB::SymbolIndex::instance();
std::unordered_map<std::string, DB::Dwarf> dwarfs; std::unordered_map<std::string, DB::Dwarf> dwarfs;
for (size_t i = 0; i < offset; ++i) { for (size_t i = 0; i < offset; ++i)
{
frames.value()[i].virtual_addr = frame_pointers[i]; frames.value()[i].virtual_addr = frame_pointers[i];
} }
@ -217,7 +213,8 @@ static void symbolize(const void * const * frame_pointers, size_t offset, size_t
auto dwarf_it = dwarfs.try_emplace(object->name, *object->elf).first; auto dwarf_it = dwarfs.try_emplace(object->name, *object->elf).first;
DB::Dwarf::LocationInfo location; DB::Dwarf::LocationInfo location;
if (dwarf_it->second.findAddress(uintptr_t(current_frame.physical_addr), location, DB::Dwarf::LocationInfoMode::FAST)) { if (dwarf_it->second.findAddress(uintptr_t(current_frame.physical_addr), location, DB::Dwarf::LocationInfoMode::FAST))
{
current_frame.file = location.file.toString(); current_frame.file = location.file.toString();
current_frame.line = location.line; current_frame.line = location.line;
} }
@ -239,8 +236,9 @@ static void symbolize(const void * const * frame_pointers, size_t offset, size_t
current_frame.symbol = "?"; current_frame.symbol = "?";
} }
} }
# else #else
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i)
{
frames.value()[i].virtual_addr = frame_pointers[i]; frames.value()[i].virtual_addr = frame_pointers[i];
} }
UNUSED(offset); UNUSED(offset);
@ -308,14 +306,16 @@ const StackTrace::FramePointers & StackTrace::getFramePointers() const
const StackTrace::Frames & StackTrace::getFrames() const const StackTrace::Frames & StackTrace::getFrames() const
{ {
if (!frames.has_value()) { if (!frames.has_value())
{
frames = {{}}; frames = {{}};
symbolize(frame_pointers.data(), offset, size, frames); symbolize(frame_pointers.data(), offset, size, frames);
} }
return frames; return frames;
} }
static void toStringEveryLineImpl(const StackTrace::Frames & frames, size_t offset, size_t size, std::function<void(const std::string &)> callback) static void
toStringEveryLineImpl(const StackTrace::Frames & frames, size_t offset, size_t size, std::function<void(const std::string &)> callback)
{ {
if (size == 0) if (size == 0)
return callback("<Empty trace>"); return callback("<Empty trace>");
@ -324,7 +324,7 @@ static void toStringEveryLineImpl(const StackTrace::Frames & frames, size_t offs
for (size_t i = offset; i < size; ++i) for (size_t i = offset; i < size; ++i)
{ {
const StackTrace::Frame& current_frame = frames.value()[i]; const StackTrace::Frame & current_frame = frames.value()[i];
out << i << ". "; out << i << ". ";
if (current_frame.file.has_value() && current_frame.line.has_value()) if (current_frame.file.has_value() && current_frame.line.has_value())
@ -338,7 +338,8 @@ static void toStringEveryLineImpl(const StackTrace::Frames & frames, size_t offs
} }
out << " @ " << current_frame.physical_addr; out << " @ " << current_frame.physical_addr;
if (current_frame.object.has_value()) { if (current_frame.object.has_value())
{
out << " in " << current_frame.object.value(); out << " in " << current_frame.object.value();
} }
@ -362,7 +363,8 @@ void StackTrace::toStringEveryLine(std::function<void(const std::string &)> call
toStringEveryLineImpl(getFrames(), offset, size, std::move(callback)); toStringEveryLineImpl(getFrames(), offset, size, std::move(callback));
} }
void StackTrace::resetFrames() { void StackTrace::resetFrames()
{
frames.reset(); frames.reset();
} }