blob: ef4146e43d196b62aa1225b7a9ae26929682295b (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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
|