Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarException_unix.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarException_unix.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/core/StarException_unix.cpp')
-rw-r--r--source/core/StarException_unix.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/source/core/StarException_unix.cpp b/source/core/StarException_unix.cpp
new file mode 100644
index 0000000..db23c7c
--- /dev/null
+++ b/source/core/StarException_unix.cpp
@@ -0,0 +1,136 @@
+#include "StarException.hpp"
+#include "StarCasting.hpp"
+#include "StarLogging.hpp"
+
+#include <execinfo.h>
+#include <cstdlib>
+
+namespace Star {
+
+static size_t const StackLimit = 256;
+
+typedef pair<Array<void*, StackLimit>, size_t> StackCapture;
+
+inline StackCapture captureStack() {
+ StackCapture stackCapture;
+ stackCapture.second = backtrace(stackCapture.first.ptr(), StackLimit);
+ return stackCapture;
+}
+
+OutputProxy outputStack(StackCapture stack) {
+ return OutputProxy([stack = move(stack)](std::ostream & os) {
+ char** symbols = backtrace_symbols(stack.first.ptr(), stack.second);
+ for (size_t i = 0; i < stack.second; ++i) {
+ os << symbols[i];
+ if (i + 1 < stack.second)
+ os << std::endl;
+ }
+
+ if (stack.second == StackLimit)
+ os << std::endl << "[Stack Output Limit Reached]";
+
+ ::free(symbols);
+ });
+}
+
+StarException::StarException() noexcept
+ : StarException(std::string("StarException")) {}
+
+StarException::~StarException() noexcept {}
+
+StarException::StarException(std::string message) noexcept
+ : StarException("StarException", move(message)) {}
+
+StarException::StarException(std::exception const& cause) noexcept
+ : StarException("StarException", std::string(), cause) {}
+
+StarException::StarException(std::string message, std::exception const& cause) noexcept
+ : StarException("StarException", move(message), cause) {}
+
+const char* StarException::what() const throw() {
+ if (m_whatBuffer.empty()) {
+ std::ostringstream os;
+ m_printException(os, false);
+ m_whatBuffer = os.str();
+ }
+ return m_whatBuffer.c_str();
+}
+
+StarException::StarException(char const* type, std::string message) noexcept {
+ auto printException = [](std::ostream& os, bool fullStacktrace, char const* type, std::string message, StackCapture stack) {
+ os << "(" << type << ")";
+ if (!message.empty())
+ os << " " << message;
+
+ if (fullStacktrace) {
+ os << std::endl;
+ os << outputStack(stack);
+ }
+ };
+
+ m_printException = bind(printException, _1, _2, type, move(message), captureStack());
+}
+
+StarException::StarException(char const* type, std::string message, std::exception const& cause) noexcept
+ : StarException(type, move(message)) {
+ auto printException = [](std::ostream& os, bool fullStacktrace, function<void(std::ostream&, bool)> self, function<void(std::ostream&, bool)> cause) {
+ self(os, fullStacktrace);
+ os << std::endl << "Caused by: ";
+ cause(os, fullStacktrace);
+ };
+
+ std::function<void(std::ostream&, bool)> printCause;
+ if (auto starException = as<StarException>(&cause)) {
+ printCause = bind(starException->m_printException, _1, _2);
+ } else {
+ printCause = bind([](std::ostream& os, bool, std::string causeWhat) {
+ os << "std::exception: " << causeWhat;
+ }, _1, _2, std::string(cause.what()));
+ }
+
+ m_printException = bind(printException, _1, _2, m_printException, move(printCause));
+}
+
+std::string printException(std::exception const& e, bool fullStacktrace) {
+ std::ostringstream os;
+ printException(os, e, fullStacktrace);
+ return os.str();
+}
+
+void printException(std::ostream& os, std::exception const& e, bool fullStacktrace) {
+ if (auto starException = as<StarException>(&e))
+ starException->m_printException(os, fullStacktrace);
+ else
+ os << "std::exception: " << e.what();
+}
+
+OutputProxy outputException(std::exception const& e, bool fullStacktrace) {
+ if (auto starException = as<StarException>(&e))
+ return OutputProxy(bind(starException->m_printException, _1, fullStacktrace));
+ else
+ return OutputProxy(bind([](std::ostream& os, std::string what) { os << "std::exception: " << what; }, _1, std::string(e.what())));
+}
+
+void printStack(char const* message) {
+ Logger::info("Stack Trace (%s)...\n%s", message, outputStack(captureStack()));
+}
+
+void fatalError(char const* message, bool showStackTrace) {
+ if (showStackTrace)
+ Logger::error("Fatal Error: %s\n%s", message, outputStack(captureStack()));
+ else
+ Logger::error("Fatal Error: %s", message);
+
+ std::abort();
+}
+
+void fatalException(std::exception const& e, bool showStackTrace) {
+ if (showStackTrace)
+ Logger::error("Fatal Exception caught: %s\nCaught at:\n%s", outputException(e, true), outputStack(captureStack()));
+ else
+ Logger::error("Fatal Exception caught: %s", outputException(e, showStackTrace));
+
+ std::abort();
+}
+
+}