aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc
diff options
context:
space:
mode:
authoriddqd <iddqd@yandex-team.com>2024-12-19 10:46:06 +0300
committeriddqd <iddqd@yandex-team.com>2024-12-19 10:59:56 +0300
commitbb0840c0025a75dd3b85b746ebcec7deb7d9fe1c (patch)
tree85bc5522e873d9d5c37df278f0300c26fe9e729e /contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc
parent1353077f79bb3547792b2fc86c22a695f0bc76f9 (diff)
downloadydb-bb0840c0025a75dd3b85b746ebcec7deb7d9fe1c.tar.gz
Add contib/libs/breakpad to export
commit_hash:9d85255f8d9249f14105e4626bf4484805b8aed4
Diffstat (limited to 'contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc')
-rw-r--r--contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc85
1 files changed, 85 insertions, 0 deletions
diff --git a/contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc b/contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc
new file mode 100644
index 0000000000..ef4146e43d
--- /dev/null
+++ b/contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc
@@ -0,0 +1,85 @@
+#include "exception_trap.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include <string>
+#include <typeinfo>
+
+namespace google_breakpad {
+
+// ExceptionDescriptor
+
+void ExceptionDescriptor::initialize(const char* type_name, const char* message) noexcept {
+ std::strncpy(type_name_.data(), type_name, type_name_.size() - 1);
+ std::strncpy(message_.data(), message, message_.size() - 1);
+}
+
+bool ExceptionDescriptor::isEmpty() const noexcept {
+ return message_[0] == '\0' && type_name_[0] == '\0';
+}
+
+const char* ExceptionDescriptor::getTypeName() const noexcept {
+ return type_name_.data();
+}
+
+const char* ExceptionDescriptor::getMessage() const noexcept {
+ return message_.data();
+}
+
+// ExceptionTrap
+
+bool ExceptionTrap::initializeOnce(const char* type_name, const char* message) noexcept {
+ if (!initialized_.test_and_set()) {
+ descriptor_.initialize(type_name, message);
+ return true;
+ }
+
+ return false;
+}
+
+ExceptionTrap& ExceptionTrap::getInstance() noexcept {
+ static ExceptionTrap instance{};
+
+ return instance;
+}
+
+void ExceptionTrap::setupTerminateHandler() {
+ getInstance().original_terminate_handler_ = std::set_terminate(
+ ExceptionTrap::terminate_handler);
+}
+
+const ExceptionDescriptor& ExceptionTrap::getCurrentException() const noexcept {
+ return descriptor_;
+}
+
+[[ noreturn ]] void ExceptionTrap::terminate() const noexcept(detail::can_catch_within_noexcept) {
+ if(original_terminate_handler_ != nullptr) {
+ try {
+ original_terminate_handler_();
+ } catch (...) {} // suppress all exceptions to avoid terminate recursion
+ }
+ std::abort();
+}
+
+[[ noreturn ]] void ExceptionTrap::terminate_handler() noexcept(detail::can_catch_within_noexcept) {
+ try {
+ const auto& e_ptr = std::current_exception(); // can throw bad_alloc
+
+ if (e_ptr != nullptr) {
+ std::rethrow_exception(e_ptr);
+ }
+ } catch (const std::exception& e) {
+ getInstance().initializeOnce(typeid(e).name(), e.what());
+ } catch (const std::string& e) {
+ getInstance().initializeOnce(typeid(e).name(), e.c_str());
+ } catch (const char* e) {
+ getInstance().initializeOnce(typeid(e).name(), e);
+ } catch (...) {
+ getInstance().initializeOnce("Unknown", "Unknown");
+ }
+
+ getInstance().terminate();
+}
+
+} //namespace google_breakpad