aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/yexception.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/yexception.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/yexception.cpp')
-rw-r--r--util/generic/yexception.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/util/generic/yexception.cpp b/util/generic/yexception.cpp
new file mode 100644
index 0000000000..2ce6c4369d
--- /dev/null
+++ b/util/generic/yexception.cpp
@@ -0,0 +1,122 @@
+#include "bt_exception.h"
+#include "yexception.h"
+
+#include <util/system/backtrace.h>
+#include <util/system/type_name.h>
+
+#include <cxxabi.h>
+
+#include <stdexcept>
+
+#include <cstdio>
+
+TString FormatExc(const std::exception& exception) {
+ return TString::Join(TStringBuf("("), TypeName(exception), TStringBuf(") "), exception.what());
+}
+
+TString CurrentExceptionMessage() {
+ auto exceptionPtr = std::current_exception();
+ if (exceptionPtr) {
+ try {
+ std::rethrow_exception(exceptionPtr);
+ } catch (const yexception& e) {
+ const TBackTrace* bt = e.BackTrace();
+
+ if (bt) {
+ return TString::Join(bt->PrintToString(), TStringBuf("\n"), FormatExc(e));
+ }
+
+ return FormatExc(e);
+ } catch (const std::exception& e) {
+ return FormatExc(e);
+ } catch (...) {
+ }
+
+ return "unknown error";
+ }
+
+ return "(NO EXCEPTION)";
+}
+
+bool UncaughtException() noexcept {
+// FIXME: use std::uncaught_exceptions() unconditionally after DEVTOOLS-8811
+#if defined(__cpp_lib_uncaught_exceptions) && !defined(_LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS)
+ return std::uncaught_exceptions() > 0;
+#else
+ return std::uncaught_exception();
+#endif
+}
+
+std::string CurrentExceptionTypeName() {
+#if defined(_linux_) || defined(_darwin_)
+ std::type_info* currentExceptionTypePtr = abi::__cxa_current_exception_type();
+ if (currentExceptionTypePtr) {
+ return TypeName(*currentExceptionTypePtr);
+ }
+#endif
+ //There is no abi::__cxa_current_exception_type() on Windows.
+ //Emulated it with rethrow - catch construction.
+ std::exception_ptr currentException = std::current_exception();
+ Y_ASSERT(currentException != nullptr);
+ try {
+ std::rethrow_exception(currentException);
+ } catch (const std::exception& e) {
+ return TypeName(typeid(e));
+ } catch (...) {
+ return "unknown type";
+ }
+}
+
+void TSystemError::Init() {
+ yexception& exc = *this;
+
+ exc << TStringBuf("(");
+ exc << TStringBuf(LastSystemErrorText(Status_));
+ exc << TStringBuf(") ");
+}
+
+NPrivateException::yexception::yexception() {
+ ZeroTerminate();
+}
+
+TStringBuf NPrivateException::yexception::AsStrBuf() const {
+ if (Buf_.Left()) {
+ return TStringBuf(Buf_.Data(), Buf_.Filled());
+ }
+
+ return TStringBuf(Buf_.Data(), Buf_.Filled() - 1);
+}
+
+void NPrivateException::yexception::ZeroTerminate() noexcept {
+ char* end = (char*)Buf_.Current();
+
+ if (!Buf_.Left()) {
+ --end;
+ }
+
+ *end = 0;
+}
+
+const char* NPrivateException::yexception::what() const noexcept {
+ return Buf_.Data();
+}
+
+const TBackTrace* NPrivateException::yexception::BackTrace() const noexcept {
+ return nullptr;
+}
+
+void fputs(const std::exception& e, FILE* f) {
+ char message[256];
+ size_t len = Min(sizeof(message) - 2, strlcpy(message, e.what(), sizeof(message) - 1));
+ message[len++] = '\n';
+ message[len] = 0;
+ fputs(message, f);
+}
+
+void ::NPrivate::ThrowYException(const ::NPrivate::TSimpleExceptionMessage& sm) {
+ throw sm.Location + yexception() << sm.Message;
+}
+
+void ::NPrivate::ThrowYExceptionWithBacktrace(const ::NPrivate::TSimpleExceptionMessage& sm) {
+ throw sm.Location + TWithBackTrace<yexception>() << sm.Message;
+}