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.h | |
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.h')
-rw-r--r-- | contrib/libs/breakpad/src/client/linux/handler/exception_trap.h | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/contrib/libs/breakpad/src/client/linux/handler/exception_trap.h b/contrib/libs/breakpad/src/client/linux/handler/exception_trap.h new file mode 100644 index 0000000000..1a9fdb7e17 --- /dev/null +++ b/contrib/libs/breakpad/src/client/linux/handler/exception_trap.h @@ -0,0 +1,73 @@ +#pragma once + +#include <array> +#include <atomic> +#include <exception> + +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +namespace detail { + +#ifdef __ANDROID__ +// In some versions of Android NDK the 'catch' blocks may have no affect in functions +// with 'noexcept' specifier. +constexpr bool can_catch_within_noexcept = false; +#else +constexpr bool can_catch_within_noexcept = true; +#endif + +} // namespace detail + +// ExceptionDescriptor holds exception information and may be safely passed +// between terminate handler context and signal handler context. +// +class ExceptionDescriptor { +public: + // Copy |type_name| and |message| content to ExceptionDescriptor memory. + // Not thread-safe. Async-signal-safe. + // May be used in terminate handler. + void initialize(const char* type_name, const char* message) noexcept; + + // isEmpty, getTypeName, getMessage are async-signal-safe. + // May be used in signal handler. + bool isEmpty() const noexcept; + const char* getTypeName() const noexcept; + const char* getMessage() const noexcept; + +private: + std::array<char, MAX_EXC_TYPE_LEN> type_name_{{'\0'}}; + std::array<char, MAX_EXC_MSG_LEN> message_{{'\0'}}; +}; + +// Singleton class. Wraps default terminate handler with ExceptionTrap::terminate_handler. +// If terminate is caused by uncaught exception, ExceptionTrap stores information about exception +// into ExceptionDescriptor before default terminate handler will call. +class ExceptionTrap { +public: + // Initialize single instance of ExceptionTrap if not initialized and return it. + // Must be called at least once before using it in terminate handler or signal handler. + static ExceptionTrap& getInstance() noexcept; + + // Replace current terminate handler by ExceptionTrap::terminate_handler. + static void setupTerminateHandler(); + + // Return information about first exception that ExceptionTrap is "caught". + // If no exception was "caught", the empty ExceptionDescriptor will returned. + // Async-signal-safe. + const ExceptionDescriptor& getCurrentException() const noexcept; + +private: + bool initializeOnce(const char* type_name, const char* message) noexcept; + + // Call original terminate handler and abort. + [[ noreturn ]] void terminate() const noexcept(detail::can_catch_within_noexcept); + [[ noreturn ]] static void terminate_handler() noexcept(detail::can_catch_within_noexcept); + + std::atomic_flag initialized_ = ATOMIC_FLAG_INIT; + ExceptionDescriptor descriptor_{}; + std::terminate_handler original_terminate_handler_{nullptr}; +}; + +} //namespace google_breakpad |