|
6 | 6 |
|
7 | 7 | #include <set> |
8 | 8 | //#include <exception> |
| 9 | +#include <atomic> |
9 | 10 | #include <iostream> |
10 | 11 | #include "Concurrency/SpinLock.h" |
11 | 12 | #include "LifetimeSanitizer.h" |
@@ -44,6 +45,100 @@ void LifetimeSanitizer::set_enabled(bool enabled){ |
44 | 45 | LifetimeSanitizer_enabled.store(false, std::memory_order_relaxed); |
45 | 46 | } |
46 | 47 |
|
| 48 | +PA_NO_INLINE void LifetimeSanitizer::terminate_with_dump(){ |
| 49 | + // Intentionally crash the program here and let the crash dump deal with |
| 50 | + // the error reporting. |
| 51 | + |
| 52 | +#ifdef _WIN32 |
| 53 | + Sleep(500); |
| 54 | +#endif |
| 55 | + |
| 56 | + std::cerr << (char*)nullptr << std::endl; |
| 57 | +} |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | +LifetimeSanitizer::LifetimeSanitizer(const char* name) |
| 63 | + : m_token(SANITIZER_TOKEN) |
| 64 | + , m_self(this) |
| 65 | + , m_name(name) |
| 66 | +{ |
| 67 | + if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){ |
| 68 | + return; |
| 69 | + } |
| 70 | + internal_construct(); |
| 71 | +} |
| 72 | +LifetimeSanitizer::~LifetimeSanitizer(){ |
| 73 | + if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){ |
| 74 | + m_self = nullptr; |
| 75 | + return; |
| 76 | + } |
| 77 | + internal_destruct(); |
| 78 | +} |
| 79 | + |
| 80 | + |
| 81 | +LifetimeSanitizer::LifetimeSanitizer(LifetimeSanitizer&& x) |
| 82 | + : m_token(SANITIZER_TOKEN) |
| 83 | + , m_self(this) |
| 84 | + , m_name(x.m_name) |
| 85 | +{ |
| 86 | + if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){ |
| 87 | + return; |
| 88 | + } |
| 89 | + x.check_usage(); |
| 90 | + internal_construct(); |
| 91 | +} |
| 92 | +void LifetimeSanitizer::operator=(LifetimeSanitizer&& x){ |
| 93 | + if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){ |
| 94 | + return; |
| 95 | + } |
| 96 | + check_usage(); |
| 97 | + x.check_usage(); |
| 98 | +} |
| 99 | +LifetimeSanitizer::LifetimeSanitizer(const LifetimeSanitizer& x) |
| 100 | + : m_token(SANITIZER_TOKEN) |
| 101 | + , m_self(this) |
| 102 | + , m_name(x.m_name) |
| 103 | +{ |
| 104 | + if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){ |
| 105 | + return; |
| 106 | + } |
| 107 | + x.check_usage(); |
| 108 | + internal_construct(); |
| 109 | +} |
| 110 | +void LifetimeSanitizer::operator=(const LifetimeSanitizer& x){ |
| 111 | + check_usage(); |
| 112 | + x.check_usage(); |
| 113 | +} |
| 114 | + |
| 115 | + |
| 116 | + |
| 117 | +void LifetimeSanitizer::check_usage() const{ |
| 118 | + if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){ |
| 119 | + return; |
| 120 | + } |
| 121 | + |
| 122 | + if (m_token != SANITIZER_TOKEN || m_self != this){ |
| 123 | + std::cerr << "Use non-existant: " << this << " : " << m_name << std::endl; |
| 124 | + terminate_with_dump(); |
| 125 | + } |
| 126 | + |
| 127 | + if (LifetimeSanitizer_has_been_disabled){ |
| 128 | + return; |
| 129 | + } |
| 130 | + |
| 131 | + ReadSpinLock lg(sanitizer_lock); |
| 132 | + if (SANITIZER_FILTER.contains(m_name)){ |
| 133 | + std::cout << "LifetimeSanitizer - Using: " << this << " : " << m_name << std::endl; |
| 134 | + } |
| 135 | + auto iter = sanitizer_map.find(this); |
| 136 | + if (iter != sanitizer_map.end()){ |
| 137 | + return; |
| 138 | + } |
| 139 | + std::cerr << "Use non-existant: " << this << " : " << m_name << std::endl; |
| 140 | + terminate_with_dump(); |
| 141 | +} |
47 | 142 |
|
48 | 143 |
|
49 | 144 | void LifetimeSanitizer::internal_construct(){ |
@@ -93,42 +188,5 @@ void LifetimeSanitizer::internal_destruct(){ |
93 | 188 |
|
94 | 189 |
|
95 | 190 |
|
96 | | -void LifetimeSanitizer::internal_check_usage() const{ |
97 | | - if (m_token != SANITIZER_TOKEN || m_self != this){ |
98 | | - std::cerr << "Use non-existant: " << this << " : " << m_name << std::endl; |
99 | | - terminate_with_dump(); |
100 | | - } |
101 | | - |
102 | | - if (LifetimeSanitizer_has_been_disabled){ |
103 | | - return; |
104 | | - } |
105 | | - |
106 | | - ReadSpinLock lg(sanitizer_lock); |
107 | | - if (SANITIZER_FILTER.contains(m_name)){ |
108 | | - std::cout << "LifetimeSanitizer - Using: " << this << " : " << m_name << std::endl; |
109 | | - } |
110 | | - auto iter = sanitizer_map.find(this); |
111 | | - if (iter != sanitizer_map.end()){ |
112 | | - return; |
113 | | - } |
114 | | - std::cerr << "Use non-existant: " << this << " : " << m_name << std::endl; |
115 | | - terminate_with_dump(); |
116 | | -} |
117 | | - |
118 | | - |
119 | | -PA_NO_INLINE void LifetimeSanitizer::terminate_with_dump(){ |
120 | | - // Intentionally crash the program here and let the crash dump deal with |
121 | | - // the error reporting. |
122 | | - |
123 | | -#ifdef _WIN32 |
124 | | - Sleep(500); |
125 | | -#endif |
126 | | - |
127 | | - std::cerr << (char*)nullptr << std::endl; |
128 | | -} |
129 | | - |
130 | | - |
131 | | - |
132 | | - |
133 | 191 | #endif |
134 | 192 | } |
0 commit comments