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/crash/SignalSafe.hpp | |
| parent | 3cf0280b11f370c11e6839275e547779a33f4a19 (diff) | |
crashReporter: cleanup code (#12534)
various code cleanups, reorders, move off of global NS
Diffstat (limited to 'src/debug/crash/SignalSafe.hpp')
| -rw-r--r-- | src/debug/crash/SignalSafe.hpp | 203 |
1 files changed, 203 insertions, 0 deletions
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); +} |
