5#include "client/crash_report_database.h"
6#include "client/crashpad_client.h"
7#include "client/settings.h"
8#include <spdlog/spdlog.h>
15#include <sys/socket.h>
33 auto database = crashpad::CrashReportDatabase::Initialize(reportsDir);
34 if (database ==
nullptr)
36 throw std::ios_base::failure(
"Can't initialize crash report database");
40 auto *settings = database->GetSettings();
41 if (settings ==
nullptr)
43 throw std::ios_base::failure(
"Can't get crash report database settings");
45 settings->SetUploadsEnabled(
true);
51 throw std::ios_base::failure(
"Can't start crash handler");
54 _thread = std::make_unique<std::jthread>([
this](
const std::stop_token &sToken) {
threadFunc(sToken); });
60 while (!stopToken.stop_requested())
69 spdlog::info(
"Crashpad handler closed");
80 catch (
const std::exception &e)
82 spdlog::error(
"Crashpad failed: {}", e.what());
93 socklen_t len =
sizeof(error);
96 const int result = getsockopt(sockId, SOL_SOCKET, SO_ERROR, &error, &len);
97 return result == 0 && error == 0 && recv(sockId, &buff, 1, MSG_PEEK | MSG_DONTWAIT) != 0;
102 std::array<char, FILENAME_MAX> pathBuffer{
'\0'};
103 auto bytes = readlink(
"/proc/self/exe", pathBuffer.data(),
sizeof(pathBuffer));
105 auto path = std::string(pathBuffer.data(), bytes == -1 ? 0 :
static_cast<size_t>(bytes));
106 auto lastDelimPos = path.find_last_of(
'/');
107 return (lastDelimPos == std::string::npos) ?
"" : path.substr(0, lastDelimPos);
115 if (!crashpad::CrashpadClient::GetHandlerSocket(&sockId, &processId))
134 std::ofstream ofile(filePath);
135 if (!ofile.is_open())
137 throw std::invalid_argument(
"Can't open file: " + filePath);
141 std::ifstream maps(
"/proc/self/maps");
144 while (std::getline(maps, line))
148 std::istringstream iss(line);
154 std::string pathname;
155 iss >> address >> perms >> offset >> dev >> inode >> pathname;
158 if (pathname.find(
".so") != std::string::npos && perms.find(
"r-x") != std::string::npos)
161 const std::string start = address.substr(0, address.find(
'-'));
164 const unsigned long addr = std::stoul(start,
nullptr, 16);
166 ofile << pathname <<
" " << addr <<
'\n';
171Tracer::Tracer(std::shared_ptr<std::atomic_flag> checkFlag, std::string serverPath, std::string serverProxy,
172 const std::string &crashpadHandlerPath,
const std::string &reportPath,
173 std::vector<base::FilePath> attachments)
179 _handlerPath = crashpadHandlerPath.empty() ? selfDir +
"/crashpad_handler" : crashpadHandlerPath;
180 _reportPath = reportPath.empty() ? selfDir : reportPath;
184 {{
"name", PROJECT_NAME},
185 {
"version", PROJECT_FULL_REVISION},
186 {
"build_info", PROJECT_BUILD_DATE + std::string(
" ") + PROJECT_BUILD_TIME + std::string(
" ") + BUILD_TYPE},
187 {
"compiler_info", COMPILER_NAME + std::string(
" ") + COMPILER_VERSION}});
constexpr int SLEEP_INTERVAL_MS
constexpr auto CRASHPAD_RETRY_COUNT
static bool checkSocketIsRunning(int sockId)
static void dumpSharedLibraryInfo(const std::string &filePath)
std::unique_ptr< crashpad::CrashpadClient > _clientHandler
std::unique_ptr< std::jthread > _thread
std::vector< base::FilePath > _attachments
std::shared_ptr< std::atomic_flag > _checkFlag
static std::string getSelfExecutableDir()
std::map< std::string, std::string > _annotations
void threadFunc(const std::stop_token &stopToken) const noexcept
Tracer(std::shared_ptr< std::atomic_flag > checkFlag, std::string serverPath="", std::string serverProxy="", const std::string &crashpadHandlerPath="", const std::string &reportPath="", std::vector< base::FilePath > attachments={})
static bool checkPidIsRunning(pid_t processId)