aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsvkrasnov <svkrasnov@yandex-team.ru>2022-02-15 13:44:41 +0300
committersvkrasnov <svkrasnov@yandex-team.ru>2022-02-15 13:44:41 +0300
commit19819502b97c522946fb88cacc5c7ea42a6dbec8 (patch)
tree3d9b598232d4e5bfda2f02a9218d67c60cd798c6
parent441ade95e65652a8c592dfa3a88c14cddcf137f6 (diff)
downloadydb-19819502b97c522946fb88cacc5c7ea42a6dbec8.tar.gz
IGNIETFERRO-1975, BIGRT-39: add TBackTrace::FromCurrentException() to CurrentExceptionMessage()
support TBackTrace::FromCurrentException() in CurrentExceptionMessage() ref:ca43c6538722fc9d169d92f85395093a21136884
-rw-r--r--util/generic/yexception.cpp30
-rw-r--r--util/generic/yexception_ut.cpp45
2 files changed, 69 insertions, 6 deletions
diff --git a/util/generic/yexception.cpp b/util/generic/yexception.cpp
index 26c75b5f51..7bfed2878d 100644
--- a/util/generic/yexception.cpp
+++ b/util/generic/yexception.cpp
@@ -14,21 +14,39 @@ TString FormatExc(const std::exception& exception) {
return TString::Join(TStringBuf("("), TypeName(exception), TStringBuf(") "), exception.what());
}
+static TString BackTraceToString(const TBackTrace& backtrace) {
+ try {
+ Y_ENSURE(backtrace.size() > 0, "backtrace is empty");
+ return backtrace.PrintToString();
+ } catch (const std::exception& e) {
+ return TString::Join("Failed to print backtrace: ", FormatExc(e));
+ }
+}
+
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));
+ const TBackTrace* btPtr;
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+ TBackTrace backtrace = TBackTrace::FromCurrentException();
+ btPtr = &backtrace;
+#else
+ btPtr = e.BackTrace();
+ if (!btPtr) {
+ return FormatExc(e);
}
-
- return FormatExc(e);
+#endif
+ return TString::Join(BackTraceToString(*btPtr), TStringBuf("\n"), FormatExc(e));
} catch (const std::exception& e) {
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+ TBackTrace backtrace = TBackTrace::FromCurrentException();
+ return TString::Join(BackTraceToString(backtrace), TStringBuf("\n"), FormatExc(e));
+#else
return FormatExc(e);
+#endif
} catch (...) {
}
diff --git a/util/generic/yexception_ut.cpp b/util/generic/yexception_ut.cpp
index cb3e29fed8..771ae2a9ca 100644
--- a/util/generic/yexception_ut.cpp
+++ b/util/generic/yexception_ut.cpp
@@ -15,6 +15,7 @@ static inline void Throw2DontMove() {
#include <util/random/mersenne.h>
#include <util/stream/output.h>
#include <util/string/subst.h>
+#include <util/string/split.h>
#include "yexception_ut.h"
#include "bt_exception.h"
@@ -48,6 +49,8 @@ class TExceptionTest: public TTestBase {
UNIT_TEST(TestBackTrace)
UNIT_TEST(TestEnsureWithBackTrace1)
UNIT_TEST(TestEnsureWithBackTrace2)
+ UNIT_TEST(TestCurrentExceptionMessageWithLIBUNWIND)
+ UNIT_TEST(TestCurrentExceptionMessageWithInvalidBacktraceFormatter)
UNIT_TEST(TestRethrowAppend)
UNIT_TEST(TestMacroOverload)
UNIT_TEST(TestMessageCrop)
@@ -128,6 +131,48 @@ private:
UNIT_ASSERT(false);
}
+ inline void TestCurrentExceptionMessageWithLIBUNWIND() {
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+ try {
+ throw std::logic_error("some exception"); // is instance of std::exception
+ UNIT_ASSERT(false);
+ } catch (...) {
+ TString exceptionMessage = CurrentExceptionMessage();
+ UNIT_ASSERT(exceptionMessage.Contains("(std::logic_error) some exception"));
+ TVector<TString> backtraceStrs = StringSplitter(exceptionMessage).Split('\n');
+ UNIT_ASSERT(backtraceStrs.size() > 1);
+ }
+#endif
+ }
+
+ inline void TestCurrentExceptionMessageWithInvalidBacktraceFormatter() {
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+ auto invalidFormatter = [](IOutputStream*, void* const*, size_t) {
+ Throw2DontMove();
+ };
+ SetFormatBackTraceFn(invalidFormatter);
+
+ try {
+ Throw1DontMove();
+ UNIT_ASSERT(false);
+ } catch (...) {
+ TString expected = "Failed to print backtrace: (yexception) "
+ "util/generic/yexception_ut.cpp:8: 1 qw 12.1\n"
+ "(yexception) util/generic/yexception_ut.cpp:4: blabla";
+ UNIT_ASSERT_EQUAL(CurrentExceptionMessage(), expected);
+ }
+ try {
+ throw std::logic_error("std exception");
+ UNIT_ASSERT(false);
+ } catch (...) {
+ TString expected = "Failed to print backtrace: (yexception) "
+ "util/generic/yexception_ut.cpp:8: 1 qw 12.1\n"
+ "(std::logic_error) std exception";
+ UNIT_ASSERT_EQUAL(CurrentExceptionMessage(), expected);
+ }
+#endif
+ }
+
inline void TestVirtualInheritance() {
TStringStream ss;