Print build id in crash messages

This commit is contained in:
Alexey Milovidov 2020-06-20 12:07:05 +03:00
parent 32c7ff7d2c
commit ead4a2cfd9
4 changed files with 57 additions and 24 deletions

View File

@ -50,6 +50,7 @@
#include <Common/getMultipleKeysFromConfig.h>
#include <Common/ClickHouseRevision.h>
#include <Common/Config/ConfigProcessor.h>
#include <Common/SymbolIndex.h>
#if !defined(ARCADIA_BUILD)
# include <Common/config_version.h>
@ -236,7 +237,8 @@ private:
void onTerminate(const std::string & message, UInt32 thread_num) const
{
LOG_FATAL(log, "(version {}{}) (from thread {}) {}", VERSION_STRING, VERSION_OFFICIAL, thread_num, message);
LOG_FATAL(log, "(version {}{}, {}) (from thread {}) {}",
VERSION_STRING, VERSION_OFFICIAL, daemon.build_id_info, thread_num, message);
}
void onFault(
@ -249,17 +251,15 @@ private:
{
LOG_FATAL(log, "########################################");
if (query_id.empty())
{
std::stringstream message;
message << "(version " << VERSION_STRING << VERSION_OFFICIAL << ")";
message << " (from thread " << thread_num << ")";
if (query_id.empty())
message << " (no query)";
else
message << " (query_id: " << query_id << ")";
message << " Received signal " << strsignal(sig) << " (" << sig << ").";
LOG_FATAL(log, message.str());
LOG_FATAL(log, "(version {}{}, {}) (from thread {}) (no query) Received signal {} ({})",
VERSION_STRING, VERSION_OFFICIAL, daemon.build_id_info, thread_num, strsignal(sig), sig);
}
else
{
LOG_FATAL(log, "(version {}{}, {}) (from thread {}) (query_id: {}) Received signal {} ({})",
VERSION_STRING, VERSION_OFFICIAL, daemon.build_id_info, thread_num, query_id, strsignal(sig), sig);
}
LOG_FATAL(log, signalToErrorMessage(sig, info, context));
@ -292,17 +292,15 @@ static void sanitizerDeathCallback()
StringRef query_id = DB::CurrentThread::getQueryId(); /// This is signal safe.
if (query_id.empty())
{
std::stringstream message;
message << "(version " << VERSION_STRING << VERSION_OFFICIAL << ")";
message << " (from thread " << getThreadId() << ")";
if (query_id.size == 0)
message << " (no query)";
else
message << " (query_id: " << query_id << ")";
message << " Sanitizer trap.";
LOG_FATAL(log, message.str());
LOG_FATAL(log, "(version {}{}, {}) (from thread {}) (no query) Sanitizer trap.",
VERSION_STRING, VERSION_OFFICIAL, daemon.build_id_info, thread_num);
}
else
{
LOG_FATAL(log, "(version {}{}, {}) (from thread {}) (query_id: {}) Sanitizer trap.",
VERSION_STRING, VERSION_OFFICIAL, daemon.build_id_info, thread_num, query_id);
}
/// Just in case print our own stack trace. In case when llvm-symbolizer does not work.
@ -711,6 +709,12 @@ void BaseDaemon::initializeTerminationAndSignalProcessing()
signal_listener = std::make_unique<SignalListener>(*this);
signal_listener_thread.start(*signal_listener);
String build_id_hex = DB::SymbolIndex::instance().getBuildIDHex();
if (build_id_hex.empty())
build_id_info = "no build id";
else
build_id_info = "build id: " + build_id_hex;
}
void BaseDaemon::logRevision() const

View File

@ -198,6 +198,8 @@ protected:
std::string config_path;
DB::ConfigProcessor::LoadedConfig loaded_config;
Poco::Util::AbstractConfiguration * last_configuration = nullptr;
String build_id_info;
};

View File

@ -1,6 +1,7 @@
#if defined(__ELF__) && !defined(__FreeBSD__)
#include <Common/SymbolIndex.h>
#include <Common/hex.h>
#include <algorithm>
#include <optional>
@ -276,15 +277,21 @@ bool searchAndCollectSymbolsFromELFSymbolTable(
void collectSymbolsFromELF(dl_phdr_info * info,
std::vector<SymbolIndex::Symbol> & symbols,
std::vector<SymbolIndex::Object> & objects)
std::vector<SymbolIndex::Object> & objects,
String & build_id)
{
std::string object_name = info->dlpi_name;
String our_build_id = getBuildIDFromProgramHeaders(info);
/// If the name is empty - it's main executable.
/// Find a elf file for the main executable.
if (object_name.empty())
{
object_name = "/proc/self/exe";
build_id = our_build_id;
}
std::error_code ec;
std::filesystem::path canonical_path = std::filesystem::canonical(object_name, ec);
@ -298,7 +305,6 @@ void collectSymbolsFromELF(dl_phdr_info * info,
object_name = std::filesystem::exists(debug_info_path) ? debug_info_path : canonical_path;
/// But we have to compare Build ID to check that debug info corresponds to the same executable.
String our_build_id = getBuildIDFromProgramHeaders(info);
SymbolIndex::Object object;
object.elf = std::make_unique<Elf>(object_name);
@ -343,7 +349,7 @@ int collectSymbols(dl_phdr_info * info, size_t, void * data_ptr)
SymbolIndex::Data & data = *reinterpret_cast<SymbolIndex::Data *>(data_ptr);
collectSymbolsFromProgramHeaders(info, data.symbols);
collectSymbolsFromELF(info, data.symbols, data.objects);
collectSymbolsFromELF(info, data.symbols, data.objects, data.build_id);
/* Continue iterations */
return 0;
@ -396,6 +402,22 @@ const SymbolIndex::Object * SymbolIndex::findObject(const void * address) const
return find(address, data.objects);
}
String SymbolIndex::getBuildIDHex() const
{
String build_id_binary = getBuildID();
String build_id_hex;
build_id_hex.resize(build_id_binary.size() * 2);
char * pos = build_id_hex.data();
for (auto c : build_id_binary)
{
writeHexByteUppercase(c, pos);
pos += 2;
}
return build_id_hex;
}
SymbolIndex & SymbolIndex::instance()
{
static SymbolIndex instance;

View File

@ -45,10 +45,15 @@ public:
const std::vector<Symbol> & symbols() const { return data.symbols; }
const std::vector<Object> & objects() const { return data.objects; }
/// The BuildID that is generated by compiler.
String getBuildID() const { return data.build_id; }
String getBuildIDHex() const;
struct Data
{
std::vector<Symbol> symbols;
std::vector<Object> objects;
String build_id;
};
private:
Data data;