diff options
author | svkrasnov <svkrasnov@yandex-team.ru> | 2022-02-15 13:44:41 +0300 |
---|---|---|
committer | svkrasnov <svkrasnov@yandex-team.ru> | 2022-02-15 13:44:41 +0300 |
commit | 19819502b97c522946fb88cacc5c7ea42a6dbec8 (patch) | |
tree | 3d9b598232d4e5bfda2f02a9218d67c60cd798c6 | |
parent | 441ade95e65652a8c592dfa3a88c14cddcf137f6 (diff) | |
download | ydb-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.cpp | 30 | ||||
-rw-r--r-- | util/generic/yexception_ut.cpp | 45 |
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; |