yexception.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "bt_exception.h"
  2. #include "yexception.h"
  3. #include <util/system/backtrace.h>
  4. #include <util/system/type_name.h>
  5. #if defined(_linux_) || defined(_android_) || defined(_darwin_)
  6. #include <cxxabi.h>
  7. #endif
  8. #include <stdexcept>
  9. #include <cstdio>
  10. static void FormatExceptionTo(IOutputStream& out, const std::exception& exception) {
  11. out << "(" << TypeName(exception) << ") " << exception.what();
  12. }
  13. TString FormatExc(const std::exception& exception) {
  14. TStringStream out;
  15. FormatExceptionTo(out, exception);
  16. return out.Str();
  17. }
  18. TString CurrentExceptionMessage() {
  19. auto exceptionPtr = std::current_exception();
  20. if (exceptionPtr) {
  21. try {
  22. std::rethrow_exception(exceptionPtr);
  23. } catch (const yexception& e) {
  24. const TBackTrace* bt = e.BackTrace();
  25. if (bt) {
  26. return TString::Join(bt->PrintToString(), TStringBuf("\n"), FormatExc(e));
  27. }
  28. return FormatExc(e);
  29. } catch (const std::exception& e) {
  30. return FormatExc(e);
  31. } catch (...) {
  32. }
  33. return "unknown error";
  34. }
  35. return "(NO EXCEPTION)";
  36. }
  37. Y_DECLARE_UNUSED static void FormatBackTraceTo(IOutputStream& out, const TBackTrace& backtrace) {
  38. if (backtrace.size() == 0) {
  39. out << "backtrace is empty";
  40. return;
  41. }
  42. try {
  43. backtrace.PrintTo(out);
  44. } catch (const std::exception& e) {
  45. out << "Failed to print backtrace: ";
  46. FormatExceptionTo(out, e);
  47. }
  48. }
  49. void FormatCurrentExceptionTo(IOutputStream& out) {
  50. auto exceptionPtr = std::current_exception();
  51. if (Y_UNLIKELY(!exceptionPtr)) {
  52. out << "(NO EXCEPTION)\n";
  53. return;
  54. }
  55. #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
  56. TBackTrace backtrace = TBackTrace::FromCurrentException();
  57. #endif
  58. try {
  59. std::rethrow_exception(exceptionPtr);
  60. } catch (const std::exception& e) {
  61. out << "Caught:\n";
  62. FormatExceptionTo(out, e);
  63. out << "\n";
  64. #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
  65. FormatBackTraceTo(out, backtrace);
  66. #endif
  67. return;
  68. } catch (...) {
  69. out << "unknown error\n";
  70. return;
  71. }
  72. }
  73. TString FormatCurrentException() {
  74. TStringStream out;
  75. FormatCurrentExceptionTo(out);
  76. return out.Str();
  77. }
  78. bool UncaughtException() noexcept {
  79. return std::uncaught_exceptions() > 0;
  80. }
  81. std::string CurrentExceptionTypeName() {
  82. #if defined(_linux_) || defined(_android_) || defined(_darwin_)
  83. std::type_info* currentExceptionTypePtr = abi::__cxa_current_exception_type();
  84. if (currentExceptionTypePtr) {
  85. return TypeName(*currentExceptionTypePtr);
  86. }
  87. #endif
  88. // There is no abi::__cxa_current_exception_type() on Windows.
  89. // Emulated it with rethrow - catch construction.
  90. std::exception_ptr currentException = std::current_exception();
  91. Y_ASSERT(currentException != nullptr);
  92. try {
  93. std::rethrow_exception(currentException);
  94. } catch (const std::exception& e) {
  95. return TypeName(typeid(e));
  96. } catch (...) {
  97. return "unknown type";
  98. }
  99. }
  100. void TSystemError::Init() {
  101. yexception& exc = *this;
  102. exc << "(Error "sv
  103. << Status_
  104. << ": "sv
  105. << TStringBuf(LastSystemErrorText(Status_))
  106. << ") "sv;
  107. }
  108. NPrivateException::yexception::yexception() {
  109. ZeroTerminate();
  110. }
  111. TStringBuf NPrivateException::yexception::AsStrBuf() const {
  112. if (Buf_.Left()) {
  113. return TStringBuf(Buf_.Data(), Buf_.Filled());
  114. }
  115. return TStringBuf(Buf_.Data(), Buf_.Filled() - 1);
  116. }
  117. void NPrivateException::yexception::ZeroTerminate() noexcept {
  118. char* end = (char*)Buf_.Current();
  119. if (!Buf_.Left()) {
  120. --end;
  121. }
  122. *end = 0;
  123. }
  124. const char* NPrivateException::yexception::what() const noexcept {
  125. return Buf_.Data();
  126. }
  127. const TBackTrace* NPrivateException::yexception::BackTrace() const noexcept {
  128. return nullptr;
  129. }
  130. void fputs(const std::exception& e, FILE* f) {
  131. char message[256];
  132. size_t len = Min(sizeof(message) - 2, strlcpy(message, e.what(), sizeof(message) - 1));
  133. message[len++] = '\n';
  134. message[len] = 0;
  135. fputs(message, f);
  136. }
  137. void ::NPrivate::ThrowYException(const ::NPrivate::TSimpleExceptionMessage& sm) {
  138. throw sm.Location + yexception() << sm.Message;
  139. }
  140. void ::NPrivate::ThrowYExceptionWithBacktrace(const ::NPrivate::TSimpleExceptionMessage& sm) {
  141. throw sm.Location + TWithBackTrace<yexception>() << sm.Message;
  142. }