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 | |
| parent | 3cf0280b11f370c11e6839275e547779a33f4a19 (diff) | |
crashReporter: cleanup code (#12534)
various code cleanups, reorders, move off of global NS
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compositor.cpp | 4 | ||||
| -rw-r--r-- | src/debug/CrashReporter.hpp | 7 | ||||
| -rw-r--r-- | src/debug/crash/CrashReporter.cpp (renamed from src/debug/CrashReporter.cpp) | 83 | ||||
| -rw-r--r-- | src/debug/crash/CrashReporter.hpp | 5 | ||||
| -rw-r--r-- | src/debug/crash/SignalSafe.cpp (renamed from src/signal-safe.cpp) | 8 | ||||
| -rw-r--r-- | src/debug/crash/SignalSafe.hpp | 203 | ||||
| -rw-r--r-- | src/signal-safe.hpp | 175 |
7 files changed, 259 insertions, 226 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 643aad1b..9c812b37 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -27,7 +27,7 @@ #include <filesystem> #include <unordered_set> #include "debug/HyprCtl.hpp" -#include "debug/CrashReporter.hpp" +#include "debug/crash/CrashReporter.hpp" #ifdef USES_SYSTEMD #include <helpers/SdDaemon.hpp> // for SdNotify #endif @@ -113,7 +113,7 @@ static void handleUnrecoverableSignal(int sig) { }); alarm(15); - NCrashReporter::createAndSaveCrash(sig); + CrashReporter::createAndSaveCrash(sig); abort(); } diff --git a/src/debug/CrashReporter.hpp b/src/debug/CrashReporter.hpp deleted file mode 100644 index 0ba48e7c..00000000 --- a/src/debug/CrashReporter.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "../defines.hpp" - -namespace NCrashReporter { - void createAndSaveCrash(int sig); -};
\ No newline at end of file diff --git a/src/debug/CrashReporter.cpp b/src/debug/crash/CrashReporter.cpp index 9e871903..1b18fce4 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/crash/CrashReporter.cpp @@ -6,36 +6,43 @@ #include <cerrno> #include <sys/stat.h> #include <filesystem> -#include "../helpers/MiscFunctions.hpp" +#include "../../helpers/MiscFunctions.hpp" -#include "../plugins/PluginSystem.hpp" -#include "../signal-safe.hpp" +#include "../../plugins/PluginSystem.hpp" +#include "SignalSafe.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..."}; +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...", + "The math isn't mathing...", + "We've got an imposter in the code!", + "Well, at least the crash reporter didn't crash!", + "Everything's just fi-", + "Have you tried asking Hyprland politely not to crash?", +}; // <random> is not async-signal-safe, fake it with time(NULL) instead -char const* getRandomMessage() { +static char const* getRandomMessage() { return MESSAGES[time(nullptr) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))]; } -[[noreturn]] inline void exitWithError(char const* err) { +[[noreturn]] static 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. @@ -43,17 +50,17 @@ char const* getRandomMessage() { abort(); } -void NCrashReporter::createAndSaveCrash(int sig) { +void CrashReporter::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; + SignalSafe::CMaxLengthCString<255> reportPath; - const auto HOME = sigGetenv("HOME"); - const auto CACHE_HOME = sigGetenv("XDG_CACHE_HOME"); + const auto HOME = SignalSafe::getenv("HOME"); + const auto CACHE_HOME = SignalSafe::getenv("XDG_CACHE_HOME"); if (CACHE_HOME && CACHE_HOME[0] != '\0') { reportPath += CACHE_HOME; @@ -67,32 +74,30 @@ void NCrashReporter::createAndSaveCrash(int sig) { } int ret = mkdir(reportPath.getStr(), S_IRWXU); - //__asm__("int $3"); - if (ret < 0 && errno != EEXIST) { + 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(); + SignalSafe::CBufFileWriter<64> stderrOut(STDERR_FILENO); + stderrOut += "Hyprland has crashed :( Consult the crash report at "; + if (!reportPath.boundsExceeded()) + stderrOut += reportPath.getStr(); + else + stderrOut += "[ERROR: Crash report path does not fit into memory! Check if your $CACHE_HOME/$HOME is too deeply nested. Max 255 characters.]"; + + stderrOut += " for more information.\n"; + stderrOut.flush(); } reportFd = open(reportPath.getStr(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - if (reportFd < 0) { + if (reportFd < 0) exitWithError("Failed to open crash report path for writing"); - } } - CBufFileWriter<512> finalCrashReport(reportFd); + SignalSafe::CBufFileWriter<512> finalCrashReport(reportFd); finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n"; finalCrashReport += getRandomMessage(); @@ -101,7 +106,7 @@ void NCrashReporter::createAndSaveCrash(int sig) { finalCrashReport += "Hyprland received signal "; finalCrashReport.writeNum(sig); finalCrashReport += '('; - finalCrashReport += sigStrsignal(sig); + finalCrashReport += SignalSafe::strsignal(sig); finalCrashReport += ")\nVersion: "; finalCrashReport += GIT_COMMIT_HASH; finalCrashReport += "\nTag: "; diff --git a/src/debug/crash/CrashReporter.hpp b/src/debug/crash/CrashReporter.hpp new file mode 100644 index 00000000..661f702f --- /dev/null +++ b/src/debug/crash/CrashReporter.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace CrashReporter { + void createAndSaveCrash(int sig); +};
\ No newline at end of file diff --git a/src/signal-safe.cpp b/src/debug/crash/SignalSafe.cpp index baee7b44..22717f1b 100644 --- a/src/signal-safe.cpp +++ b/src/debug/crash/SignalSafe.cpp @@ -1,4 +1,4 @@ -#include "signal-safe.hpp" +#include "SignalSafe.hpp" #ifndef __GLIBC__ #include <signal.h> @@ -7,11 +7,13 @@ #include <unistd.h> #include <cstring> +using namespace SignalSafe; + // NOLINTNEXTLINE extern "C" char** environ; // -char const* sigGetenv(char const* name) { +char const* SignalSafe::getenv(char const* name) { const size_t len = strlen(name); for (char** var = environ; *var != nullptr; var++) { if (strncmp(*var, name, len) == 0 && (*var)[len] == '=') { @@ -21,7 +23,7 @@ char const* sigGetenv(char const* name) { return nullptr; } -char const* sigStrsignal(int sig) { +char const* SignalSafe::strsignal(int sig) { #ifdef __GLIBC__ return sigabbrev_np(sig); #elif defined(__DragonFly__) || defined(__FreeBSD__) diff --git a/src/debug/crash/SignalSafe.hpp b/src/debug/crash/SignalSafe.hpp new file mode 100644 index 00000000..8ec967fe --- /dev/null +++ b/src/debug/crash/SignalSafe.hpp @@ -0,0 +1,203 @@ +#pragma once + +#include "defines.hpp" +#include <cstring> + +namespace SignalSafe { + template <uint16_t N> + class CMaxLengthCString { + public: + CMaxLengthCString() { + m_str[0] = '\0'; + } + + void operator+=(char const* rhs) { + write(rhs, strlen(rhs)); + } + + void write(char const* data, size_t len) { + if (m_boundsExceeded || m_strPos + len >= N) { + m_boundsExceeded = true; + return; + } + memcpy(m_str + m_strPos, data, len); + m_strPos += len; + m_str[m_strPos] = '\0'; + } + + void write(char c) { + if (m_boundsExceeded || m_strPos + 1 >= N) { + m_boundsExceeded = true; + return; + } + m_str[m_strPos] = c; + m_strPos++; + } + + void writeNum(size_t num) { + size_t d = 1; + + while (num / 10 >= d) { + d *= 10; + } + + while (num > 0) { + char c = '0' + (num / d); + write(c); + num %= d; + d /= 10; + } + } + + char const* getStr() { + return m_str; + } + + bool boundsExceeded() { + return m_boundsExceeded; + } + + private: + char m_str[N]; + size_t m_strPos = 0; + bool m_boundsExceeded = false; + }; + + template <uint16_t BUFSIZE> + class CBufFileWriter { + public: + CBufFileWriter(int fd_) : m_fd(fd_) { + ; + } + + ~CBufFileWriter() { + flush(); + } + + void write(char const* data, size_t len) { + while (len > 0) { + size_t to_add = std::min(len, sc<size_t>(BUFSIZE) - m_writeBufPos); + memcpy(m_writeBuf + m_writeBufPos, data, to_add); + data += to_add; + len -= to_add; + m_writeBufPos += to_add; + if (m_writeBufPos == BUFSIZE) + flush(); + } + } + + void write(char c) { + if (m_writeBufPos == BUFSIZE) + flush(); + m_writeBuf[m_writeBufPos] = c; + m_writeBufPos++; + } + + void operator+=(char const* str) { + write(str, strlen(str)); + } + + void operator+=(std::string_view str) { + write(str.data(), str.size()); + } + + void operator+=(char c) { + write(c); + } + + void writeNum(size_t num) { + size_t d = 1; + + while (num / 10 >= d) { + d *= 10; + } + + while (num > 0) { + char c = '0' + (num / d); + write(c); + num %= d; + d /= 10; + } + } + + void writeCmdOutput(const char* cmd) { + int pipefd[2]; + if (pipe(pipefd) < 0) { + *this += "<pipe(pipefd) failed with"; + writeNum(errno); + *this += ">\n"; + return; + } + + // terminate child instead of waiting + { + struct sigaction act; + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NOCLDWAIT; +#ifdef SA_RESTORER + act.sa_restorer = NULL; +#endif + sigaction(SIGCHLD, &act, nullptr); + } + + const pid_t pid = fork(); + + if (pid < 0) { + *this += "<fork() failed with "; + writeNum(errno); + *this += ">\n"; + return; + } + + if (pid == 0) { + close(pipefd[0]); + dup2(pipefd[1], STDOUT_FILENO); + char const* const argv[] = {"/bin/sh", "-c", cmd, nullptr}; + execv("/bin/sh", cc<char* const*>(argv)); + + CBufFileWriter<64> failmsg(pipefd[1]); + failmsg += "<execv("; + failmsg += cmd; + failmsg += ") resulted in errno "; + failmsg.write(errno); + failmsg += ">\n"; + close(pipefd[1]); + abort(); + } else { + close(pipefd[1]); + int64_t len = 0; + char readbuf[256]; + while ((len = read(pipefd[0], readbuf, 256)) > 0) { + write(readbuf, len); + } + if (len < 0) { + *this += "<interrupted, read() resulted in errno "; + writeNum(errno); + *this += ">\n"; + } + close(pipefd[0]); + } + } + + void flush() { + size_t i = 0; + while (i < m_writeBufPos) { + auto written = ::write(m_fd, m_writeBuf + i, m_writeBufPos - i); + if (written <= 0) { + return; + } + i += written; + } + m_writeBufPos = 0; + } + + private: + char m_writeBuf[BUFSIZE] = {0}; + size_t m_writeBufPos = 0; + int m_fd = 0; + }; + + char const* getenv(const char* name); + char const* strsignal(int sig); +} diff --git a/src/signal-safe.hpp b/src/signal-safe.hpp deleted file mode 100644 index a48b51b0..00000000 --- a/src/signal-safe.hpp +++ /dev/null @@ -1,175 +0,0 @@ -#pragma once - -#include "defines.hpp" -#include <cstring> - -template <uint16_t N> -class CMaxLengthCString { - public: - CMaxLengthCString() { - m_str[0] = '\0'; - } - void operator+=(char const* rhs) { - write(rhs, strlen(rhs)); - } - void write(char const* data, size_t len) { - if (m_boundsExceeded || m_strPos + len >= N) { - m_boundsExceeded = true; - return; - } - memcpy(m_str + m_strPos, data, len); - m_strPos += len; - m_str[m_strPos] = '\0'; - } - void write(char c) { - if (m_boundsExceeded || m_strPos + 1 >= N) { - m_boundsExceeded = true; - return; - } - m_str[m_strPos] = c; - m_strPos++; - } - void writeNum(size_t num) { - size_t d = 1; - while (num / 10 >= d) - d *= 10; - while (num > 0) { - char c = '0' + (num / d); - write(c); - num %= d; - d /= 10; - } - } - char const* getStr() { - return m_str; - }; - bool boundsExceeded() { - return m_boundsExceeded; - }; - - private: - char m_str[N]; - size_t m_strPos = 0; - bool m_boundsExceeded = false; -}; - -template <uint16_t BUFSIZE> -class CBufFileWriter { - public: - CBufFileWriter(int fd_) : m_fd(fd_) {} - ~CBufFileWriter() { - flush(); - } - void write(char const* data, size_t len) { - while (len > 0) { - size_t to_add = std::min(len, sc<size_t>(BUFSIZE) - m_writeBufPos); - memcpy(m_writeBuf + m_writeBufPos, data, to_add); - data += to_add; - len -= to_add; - m_writeBufPos += to_add; - if (m_writeBufPos == BUFSIZE) - flush(); - } - } - void write(char c) { - if (m_writeBufPos == BUFSIZE) - flush(); - m_writeBuf[m_writeBufPos] = c; - m_writeBufPos++; - } - void operator+=(char const* str) { - write(str, strlen(str)); - } - void operator+=(std::string_view str) { - write(str.data(), str.size()); - } - void operator+=(char c) { - write(c); - } - void writeNum(size_t num) { - size_t d = 1; - while (num / 10 >= d) - d *= 10; - while (num > 0) { - char c = '0' + (num / d); - write(c); - num %= d; - d /= 10; - } - } - void writeCmdOutput(const char* cmd) { - int pipefd[2]; - if (pipe(pipefd) < 0) { - *this += "<pipe(pipefd) failed with"; - writeNum(errno); - *this += ">\n"; - return; - } - // terminate child instead of waiting - { - struct sigaction act; - act.sa_handler = SIG_DFL; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_NOCLDWAIT; -#ifdef SA_RESTORER - act.sa_restorer = NULL; -#endif - sigaction(SIGCHLD, &act, nullptr); - } - const pid_t pid = fork(); - if (pid < 0) { - *this += "<fork() failed with "; - writeNum(errno); - *this += ">\n"; - return; - } - if (pid == 0) { - close(pipefd[0]); - dup2(pipefd[1], STDOUT_FILENO); - char const* const argv[] = {"/bin/sh", "-c", cmd, nullptr}; - execv("/bin/sh", const_cast<char* const*>(argv)); - - CBufFileWriter<64> failmsg(pipefd[1]); - failmsg += "<execv("; - failmsg += cmd; - failmsg += ") resulted in errno "; - failmsg.write(errno); - failmsg += ">\n"; - close(pipefd[1]); - abort(); - } else { - close(pipefd[1]); - int64_t len = 0; - char readbuf[256]; - while ((len = read(pipefd[0], readbuf, 256)) > 0) { - write(readbuf, len); - } - if (len < 0) { - *this += "<interrupted, read() resulted in errno "; - writeNum(errno); - *this += ">\n"; - } - close(pipefd[0]); - } - } - void flush() { - size_t i = 0; - while (i < m_writeBufPos) { - auto written = ::write(m_fd, m_writeBuf + i, m_writeBufPos - i); - if (written <= 0) { - return; - } - i += written; - } - m_writeBufPos = 0; - } - - private: - char m_writeBuf[BUFSIZE] = {0}; - size_t m_writeBufPos = 0; - int m_fd = 0; -}; - -char const* sigGetenv(char const* name); - -char const* sigStrsignal(int sig); |
