From 38c25bb50d76409193db2438db60369f3868edf9 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sun, 19 Feb 2023 13:45:56 +0000 Subject: [PATCH] Added a crash reporter --- CMakeLists.txt | 3 ++ src/Compositor.cpp | 7 +++ src/debug/CrashReporter.cpp | 93 +++++++++++++++++++++++++++++++++++ src/debug/CrashReporter.hpp | 7 +++ src/helpers/MiscFunctions.cpp | 9 ++++ src/helpers/MiscFunctions.hpp | 6 +-- 6 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/debug/CrashReporter.cpp create mode 100644 src/debug/CrashReporter.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4297b451..b2e4b8b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,9 @@ target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"") target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\"") target_compile_definitions(Hyprland PRIVATE "-DGIT_DIRTY=\"${GIT_DIRTY}\"") +ADD_LINK_OPTIONS( -rdynamic ) +SET(CMAKE_ENABLE_EXPORTS TRUE) + target_link_libraries(Hyprland rt) set(CPACK_PROJECT_NAME ${PROJECT_NAME}) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 365a2c12..0b4970c2 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2,6 +2,7 @@ #include "helpers/Splashes.hpp" #include #include "debug/HyprCtl.hpp" +#include "debug/CrashReporter.hpp" #ifdef USES_SYSTEMD #include // for sd_notify #endif @@ -16,6 +17,11 @@ int handleCritSignal(int signo, void* data) { return 0; // everything went fine } +void handleSegv(int sig) { + CrashReporter::createAndSaveCrash(); + exit(SIGSEGV); +} + CCompositor::CCompositor() { wlr_log_init(WLR_INFO, NULL); @@ -61,6 +67,7 @@ CCompositor::CCompositor() { // register crit signal handler wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr); + signal(SIGSEGV, handleSegv); //wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr); m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession); diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp new file mode 100644 index 00000000..26e3938a --- /dev/null +++ b/src/debug/CrashReporter.cpp @@ -0,0 +1,93 @@ +#include "CrashReporter.hpp" +#include +#include +#include +#include + +std::string getRandomMessage() { + + const std::vector MESSAGES = {"Sorry, didn't mean to...", + "This was an accident, I swear!", + "Calm down, it was a misinput! MISINPUT!", + "Oops", + "Vaxry is going to be upset.", + "Who tried dividing by zero?!", + "Maybe you should try dusting your PC in the meantime?", + "I tried so hard, and got so far...", + "I don't feel so good...", + "*thud*", + "Well this is awkward.", + "\"stable\"", + "I hope you didn't have any unsaved progress."}; + + std::random_device dev; + std::mt19937 engine(dev()); + std::uniform_int_distribution<> distribution(0, MESSAGES.size() - 1); + + return MESSAGES[distribution(engine)]; +} + +void CrashReporter::createAndSaveCrash() { + + // get the backtrace + const int PID = getpid(); + + std::string finalCrashReport = ""; + + finalCrashReport += "--------------------------------------------\n Hyprland Crash Log\n--------------------------------------------\n"; + finalCrashReport += getRandomMessage() + "\n\n"; + + finalCrashReport += "Hyprland received signal 11 (SIGSEGV): Segmentation Fault\n\n"; + + finalCrashReport += "System info:\n"; + + struct utsname unameInfo; + uname(&unameInfo); + + finalCrashReport += + getFormat("\tSystem name: %s\n\tNode name: %s\n\tRelease: %s\n\tVersion: %s\n\n", unameInfo.sysname, unameInfo.nodename, unameInfo.release, unameInfo.version); + + const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); + + finalCrashReport += "GPU:\n\t" + GPUINFO; + + finalCrashReport += getFormat("\n\nos-release:\n\t%s\n\n\n", replaceInString(execAndGet("cat /etc/os-release"), "\n", "\n\t").c_str()); + + finalCrashReport += "Backtrace:\n"; + + void* bt[1024]; + size_t btSize; + char** btSymbols; + + btSize = backtrace(bt, 1024); + btSymbols = backtrace_symbols(bt, btSize); + + for (size_t i = 0; i < btSize; ++i) { + finalCrashReport += getFormat("\t#%i | %s\n", i, btSymbols[i]); + + std::string btSymbol = btSymbols[i]; + size_t hlPos = 0; + while (btSymbol.find("Hyprland", hlPos + 1) != std::string::npos) { + hlPos = btSymbol.find("Hyprland", hlPos + 1); + } + + if (hlPos != 0) { + const auto CMD = getFormat("addr2line -e %s -f 0x%lx", btSymbol.substr(0, hlPos + 8).c_str(), (uint64_t)bt[i]); + const auto ADDR2LINE = replaceInString(execAndGet(CMD.c_str()), "\n", "\n\t\t"); + finalCrashReport += "\t\t" + ADDR2LINE.substr(0, ADDR2LINE.length() - 2); + } + } + + free(btSymbols); + + const auto HOME = getenv("HOME"); + + if (!HOME) + return; + + std::ofstream ofs(std::string(HOME) + "/.hyprlandDump" + std::to_string(PID), std::ios::trunc); + + ofs << finalCrashReport; + + ofs.close(); +} \ No newline at end of file diff --git a/src/debug/CrashReporter.hpp b/src/debug/CrashReporter.hpp new file mode 100644 index 00000000..b607a82f --- /dev/null +++ b/src/debug/CrashReporter.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "../defines.hpp" + +namespace CrashReporter { + void createAndSaveCrash(); +}; \ No newline at end of file diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 40121de3..dcc1efbd 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -549,4 +549,13 @@ double normalizeAngleRad(double ang) { } return ang; +} + +std::string replaceInString(std::string subject, const std::string& search, const std::string& replace) { + size_t pos = 0; + while ((pos = subject.find(search, pos)) != std::string::npos) { + subject.replace(pos, search.length(), replace); + pos += replace.length(); + } + return subject; } \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 43cfb944..a5f21313 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -16,9 +16,7 @@ void logSystemInfo(); std::string execAndGet(const char*); int64_t getPPIDof(int64_t pid); int64_t configStringToInt(const std::string&); - float getPlusMinusKeywordResult(std::string in, float relative); - void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); - -double normalizeAngleRad(double ang); \ No newline at end of file +double normalizeAngleRad(double ang); +std::string replaceInString(std::string subject, const std::string& search, const std::string& replace); \ No newline at end of file