diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2025-12-03 16:01:45 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-03 16:01:45 +0000 |
| commit | 93e5e92b0ae7809ee0f64d94d51e210c476ee823 (patch) | |
| tree | 096ff92094b899ee6ed138951caf9e735a148378 /src/debug/CrashReporter.cpp | |
| parent | 3cf0280b11f370c11e6839275e547779a33f4a19 (diff) | |
crashReporter: cleanup code (#12534)
various code cleanups, reorders, move off of global NS
Diffstat (limited to 'src/debug/CrashReporter.cpp')
| -rw-r--r-- | src/debug/CrashReporter.cpp | 247 |
1 files changed, 0 insertions, 247 deletions
diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp deleted file mode 100644 index 9e871903..00000000 --- a/src/debug/CrashReporter.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "CrashReporter.hpp" -#include <fcntl.h> -#include <sys/utsname.h> -#include <link.h> -#include <ctime> -#include <cerrno> -#include <sys/stat.h> -#include <filesystem> -#include "../helpers/MiscFunctions.hpp" - -#include "../plugins/PluginSystem.hpp" -#include "../signal-safe.hpp" - -#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) -#include <sys/sysctl.h> -#endif - -static char const* const 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.", - "All these computers..."}; - -// <random> is not async-signal-safe, fake it with time(NULL) instead -char const* getRandomMessage() { - return MESSAGES[time(nullptr) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))]; -} - -[[noreturn]] inline void exitWithError(char const* err) { - write(STDERR_FILENO, err, strlen(err)); - // perror() is not signal-safe, but we use it here - // because if the crash-handler already crashed, it can't get any worse. - perror(""); - abort(); -} - -void NCrashReporter::createAndSaveCrash(int sig) { - int reportFd = -1; - - // We're in the signal handler, so we *only* have stack memory. - // To save as much stack memory as possible, - // destroy things as soon as possible. - { - CMaxLengthCString<255> reportPath; - - const auto HOME = sigGetenv("HOME"); - const auto CACHE_HOME = sigGetenv("XDG_CACHE_HOME"); - - if (CACHE_HOME && CACHE_HOME[0] != '\0') { - reportPath += CACHE_HOME; - reportPath += "/hyprland"; - } else if (HOME && HOME[0] != '\0') { - reportPath += HOME; - reportPath += "/.cache/hyprland"; - } else { - exitWithError("$CACHE_HOME and $HOME not set, nowhere to report crash\n"); - return; - } - - int ret = mkdir(reportPath.getStr(), S_IRWXU); - //__asm__("int $3"); - if (ret < 0 && errno != EEXIST) { - exitWithError("failed to mkdir() crash report directory\n"); - } - reportPath += "/hyprlandCrashReport"; - reportPath.writeNum(getpid()); - reportPath += ".txt"; - - { - CBufFileWriter<64> stderr_out(STDERR_FILENO); - stderr_out += "Hyprland has crashed :( Consult the crash report at "; - if (!reportPath.boundsExceeded()) { - stderr_out += reportPath.getStr(); - } else { - stderr_out += "[ERROR: Crash report path does not fit into memory! Check if your $CACHE_HOME/$HOME is too deeply nested. Max 255 characters.]"; - } - stderr_out += " for more information.\n"; - stderr_out.flush(); - } - - reportFd = open(reportPath.getStr(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - if (reportFd < 0) { - exitWithError("Failed to open crash report path for writing"); - } - } - CBufFileWriter<512> finalCrashReport(reportFd); - - finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n"; - finalCrashReport += getRandomMessage(); - finalCrashReport += "\n\n"; - - finalCrashReport += "Hyprland received signal "; - finalCrashReport.writeNum(sig); - finalCrashReport += '('; - finalCrashReport += sigStrsignal(sig); - finalCrashReport += ")\nVersion: "; - finalCrashReport += GIT_COMMIT_HASH; - finalCrashReport += "\nTag: "; - finalCrashReport += GIT_TAG; - finalCrashReport += "\nDate: "; - finalCrashReport += GIT_COMMIT_DATE; - finalCrashReport += "\nFlags:\n"; -#if ISDEBUG - finalCrashReport += "debug\n"; -#endif -#ifdef NO_XWAYLAND - finalCrashReport += "no xwayland\n"; -#endif - finalCrashReport += "\n"; - - if (g_pPluginSystem && g_pPluginSystem->pluginCount() > 0) { - finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n"; - - const size_t count = g_pPluginSystem->pluginCount(); - std::vector<CPlugin*> plugins(count); - g_pPluginSystem->sigGetPlugins(plugins.data(), count); - - for (size_t i = 0; i < count; i++) { - auto p = plugins[i]; - finalCrashReport += '\t'; - finalCrashReport += p->m_name; - finalCrashReport += " ("; - finalCrashReport += p->m_author; - finalCrashReport += ") "; - finalCrashReport += p->m_version; - finalCrashReport += '\n'; - } - - finalCrashReport += "\n\n"; - } - - finalCrashReport += "System info:\n"; - - { - struct utsname unameInfo; - uname(&unameInfo); - - finalCrashReport += "\tSystem name: "; - finalCrashReport += unameInfo.sysname; - finalCrashReport += "\n\tNode name: "; - finalCrashReport += unameInfo.nodename; - finalCrashReport += "\n\tRelease: "; - finalCrashReport += unameInfo.release; - finalCrashReport += "\n\tVersion: "; - finalCrashReport += unameInfo.version; - finalCrashReport += "\n\n"; - } - - finalCrashReport += "GPU:\n\t"; -#if defined(__DragonFly__) || defined(__FreeBSD__) - finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga"); -#else - finalCrashReport.writeCmdOutput("lspci -vnn | grep -E '(VGA|Display|3D)'"); -#endif - - finalCrashReport += "\n\nos-release:\n"; - finalCrashReport.writeCmdOutput("cat /etc/os-release | sed 's/^/\t/'"); - - finalCrashReport += '\n'; - finalCrashReport += getBuiltSystemLibraryNames(); - finalCrashReport += '\n'; - - // dladdr1()/backtrace_symbols()/this entire section allocates, and hence is NOT async-signal-safe. - // Make sure that we save the current known crash report information, - // so that if we are caught in a deadlock during a call to malloc(), - // there is still something to debug from. - finalCrashReport.flush(); - - finalCrashReport += "Backtrace:\n"; - - const auto CALLSTACK = getBacktrace(); - -#if defined(KERN_PROC_PATHNAME) - int mib[] = { - CTL_KERN, -#if defined(__NetBSD__) - KERN_PROC_ARGS, - -1, - KERN_PROC_PATHNAME, -#else - KERN_PROC, - KERN_PROC_PATHNAME, - -1, -#endif - }; - u_int miblen = sizeof(mib) / sizeof(mib[0]); - char exe[PATH_MAX] = "/nonexistent"; - size_t sz = sizeof(exe); - sysctl(mib, miblen, &exe, &sz, NULL, 0); - const auto FPATH = std::filesystem::canonical(exe); -#elif defined(__OpenBSD__) - // Neither KERN_PROC_PATHNAME nor /proc are supported - const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland"); -#else - const auto FPATH = std::filesystem::canonical("/proc/self/exe"); -#endif - - std::string addrs = ""; - for (size_t i = 0; i < CALLSTACK.size(); ++i) { -#ifdef __GLIBC__ - // convert in memory address to VMA address - Dl_info info; - struct link_map* linkMap; - dladdr1(CALLSTACK[i].adr, &info, rc<void**>(&linkMap), RTLD_DL_LINKMAP); - size_t vmaAddr = rc<size_t>(CALLSTACK[i].adr) - linkMap->l_addr; -#else - // musl doesn't define dladdr1 - size_t vmaAddr = (size_t)CALLSTACK[i].adr; -#endif - - addrs += std::format("0x{:x} ", vmaAddr); - } -#ifdef __clang__ - const auto CMD = std::format("llvm-addr2line -e {} -Cf {}", FPATH.c_str(), addrs); -#else - const auto CMD = std::format("addr2line -e {} -Cf {}", FPATH.c_str(), addrs); -#endif - - const auto ADDR2LINE = execAndGet(CMD.c_str()); - - std::stringstream ssin(ADDR2LINE); - - for (size_t i = 0; i < CALLSTACK.size(); ++i) { - finalCrashReport += "\t#"; - finalCrashReport.writeNum(i); - finalCrashReport += " | "; - finalCrashReport += CALLSTACK[i].desc; - std::string functionInfo; - std::string fileLineInfo; - std::getline(ssin, functionInfo); - std::getline(ssin, fileLineInfo); - finalCrashReport += std::format("\n\t\t{}\n\t\t{}\n", functionInfo, fileLineInfo); - } - - finalCrashReport += "\n\nLog tail:\n"; - - finalCrashReport += std::string_view(Debug::m_rollingLog).substr(Debug::m_rollingLog.find('\n') + 1); -} |
