diff options
author | iddqd <iddqd@yandex-team.com> | 2024-12-19 10:46:06 +0300 |
---|---|---|
committer | iddqd <iddqd@yandex-team.com> | 2024-12-19 10:59:56 +0300 |
commit | bb0840c0025a75dd3b85b746ebcec7deb7d9fe1c (patch) | |
tree | 85bc5522e873d9d5c37df278f0300c26fe9e729e /contrib/libs/breakpad/src/client/linux/handler/exception_trap.cc | |
parent | 1353077f79bb3547792b2fc86c22a695f0bc76f9 (diff) | |
download | ydb-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.cc | 85 |
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 |