Skip to content

Commit

Permalink
Attempt to debug user audio crash. Strengthen the LifetimeSanitizer, …
Browse files Browse the repository at this point in the history
…turn on by default, litter the audio stack with it.
  • Loading branch information
Mysticial committed Dec 15, 2024
1 parent 08e6797 commit c9c6343
Show file tree
Hide file tree
Showing 24 changed files with 261 additions and 166 deletions.
26 changes: 13 additions & 13 deletions Common/Cpp/CancellableScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ Cancellable::~Cancellable(){
// cout << "Deleting: " << this << endl;
}
CancellableScope* Cancellable::scope() const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
return m_scope;
}
bool Cancellable::cancelled() const noexcept{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
return m_impl->cancelled.load(std::memory_order_acquire);
}
bool Cancellable::cancel(std::exception_ptr exception) noexcept{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
CancellableData& data(*m_impl);
WriteSpinLock lg(data.lock);
if (exception && !data.exception){
Expand All @@ -62,7 +62,7 @@ bool Cancellable::cancel(std::exception_ptr exception) noexcept{
return data.cancelled.exchange(true, std::memory_order_relaxed);
}
void Cancellable::throw_if_cancelled() const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
const CancellableData& data(*m_impl);
if (!data.cancelled.load(std::memory_order_acquire)){
return;
Expand All @@ -75,7 +75,7 @@ void Cancellable::throw_if_cancelled() const{
}
}
bool Cancellable::throw_if_cancelled_with_exception() const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
const CancellableData& data(*m_impl);
if (!data.cancelled.load(std::memory_order_acquire)){
return false;
Expand All @@ -87,12 +87,12 @@ bool Cancellable::throw_if_cancelled_with_exception() const{
return true;
}
void Cancellable::attach(CancellableScope& scope){
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
m_scope = &scope;
scope += *this;
}
void Cancellable::detach() noexcept{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
if (m_scope){
*m_scope -= *this;
}
Expand Down Expand Up @@ -126,7 +126,7 @@ bool CancellableScope::cancel(std::exception_ptr exception) noexcept{
for (Cancellable* child : data.children){
// cout << "Canceling: " << child << endl;
// cout << "Canceling: " << child->name() << endl;
child->m_sanitizer.check_usage();
auto scope_check = child->m_sanitizer.check_scope();
child->cancel(exception);
}
// cout << "Done Canceling" << endl;
Expand All @@ -135,11 +135,11 @@ bool CancellableScope::cancel(std::exception_ptr exception) noexcept{
return false;
}
void CancellableScope::wait_for(std::chrono::milliseconds duration){
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
wait_until(current_time() + duration);
}
void CancellableScope::wait_until(WallClock stop){
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
throw_if_cancelled();
CancellableScopeData& data(*m_impl);
{
Expand All @@ -154,7 +154,7 @@ void CancellableScope::wait_until(WallClock stop){
throw_if_cancelled();
}
void CancellableScope::wait_until_cancel(){
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
throw_if_cancelled();
CancellableScopeData& data(*m_impl);
{
Expand All @@ -170,15 +170,15 @@ void CancellableScope::wait_until_cancel(){
}
void CancellableScope::operator+=(Cancellable& cancellable){
// cout << "Attaching: " << &cancellable << endl;
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
CancellableScopeData& data(*m_impl);
std::lock_guard<std::mutex> lg(data.lock);
throw_if_cancelled();
data.children.insert(&cancellable);
}
void CancellableScope::operator-=(Cancellable& cancellable){
// cout << "Detaching: " << &cancellable << endl;
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
CancellableScopeData& data(*m_impl);
std::lock_guard<std::mutex> lg(data.lock);
data.children.erase(&cancellable);
Expand Down
10 changes: 5 additions & 5 deletions Common/Cpp/EnumDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace PokemonAutomation{
class IntegerEnumDatabaseImpl{
public:
void add(EnumEntry entry){
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
size_t enum_value = entry.enum_value;
m_list.emplace_back(enum_value);

Expand All @@ -44,23 +44,23 @@ class IntegerEnumDatabaseImpl{
}

const EnumEntry* find(size_t value) const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
auto iter = m_map.find(value);
if (iter == m_map.end()){
return nullptr;
}
return &iter->second;
}
const EnumEntry* find_slug(const std::string& slug) const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
auto iter = m_slug_to_enum.find(slug);
if (iter == m_slug_to_enum.end()){
return nullptr;
}
return iter->second;
}
const EnumEntry* find_display(const std::string& display) const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
auto iter = m_display_to_enum.find(display);
if (iter == m_display_to_enum.end()){
return nullptr;
Expand All @@ -69,7 +69,7 @@ class IntegerEnumDatabaseImpl{
}

FixedLimitVector<size_t> all_values() const{
m_sanitizer.check_usage();
auto scope_check = m_sanitizer.check_scope();
FixedLimitVector<size_t> ret(m_map.size());
for (const auto& item : m_map){
ret.emplace_back(item.first);
Expand Down
98 changes: 19 additions & 79 deletions Common/Cpp/LifetimeSanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

#include <set>
#include <atomic>
#include <exception>
#include <iostream>
#include "Concurrency/SpinLock.h"
Expand All @@ -18,8 +17,6 @@ namespace PokemonAutomation{

#ifdef PA_SANITIZER_ENABLE

constexpr uint64_t SANITIZER_TOKEN = 0x7db76f7a6a834ef0;

SpinLock sanitizer_lock;
std::set<const LifetimeSanitizer*> sanitizer_map;

Expand All @@ -39,16 +36,7 @@ void LifetimeSanitizer::set_enabled(bool enabled){





LifetimeSanitizer::LifetimeSanitizer()
: m_token(SANITIZER_TOKEN)
, m_self(this)
{
if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){
return;
}

void LifetimeSanitizer::internal_construct(){
WriteSpinLock lg(sanitizer_lock);
#ifdef PA_SANITIZER_PRINT_ALL
std::cout << "LifetimeSanitizer - Allocating: " << this << std::endl;
Expand All @@ -59,17 +47,15 @@ LifetimeSanitizer::LifetimeSanitizer()
return;
}
std::cerr << "LifetimeSanitizer - Double allocation: " << this << std::endl;
std::terminate();
terminate_with_dump();
}
LifetimeSanitizer::~LifetimeSanitizer(){
void LifetimeSanitizer::internal_destruct(){
void* self = m_self;
m_self = nullptr;
if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){
return;
}

if (m_token != SANITIZER_TOKEN || self != this){
std::cerr << "LifetimeSanitizer - Free non-existant: " << this << std::endl;
std::terminate();
terminate_with_dump();
}

WriteSpinLock lg(sanitizer_lock);
Expand All @@ -89,73 +75,18 @@ LifetimeSanitizer::~LifetimeSanitizer(){
}

std::cerr << "LifetimeSanitizer - Free non-existant: " << this << std::endl;
std::terminate();
}



LifetimeSanitizer::LifetimeSanitizer(LifetimeSanitizer&& x)
: m_token(SANITIZER_TOKEN)
, m_self(this)
{
if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){
return;
}
x.check_usage();

WriteSpinLock lg(sanitizer_lock);
#ifdef PA_SANITIZER_PRINT_ALL
std::cout << "LifetimeSanitizer - Allocating (move-construct): " << this << std::endl;
#endif
auto iter = sanitizer_map.find(this);
if (iter == sanitizer_map.end()){
sanitizer_map.insert(this);
return;
}
std::cerr << "LifetimeSanitizer - Double allocation: " << this << std::endl;
std::terminate();
}
void LifetimeSanitizer::operator=(LifetimeSanitizer&& x){
if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){
return;
}
check_usage();
x.check_usage();
terminate_with_dump();
}



LifetimeSanitizer::LifetimeSanitizer(const LifetimeSanitizer& x){
if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){
return;
}
x.check_usage();

WriteSpinLock lg(sanitizer_lock);
#ifdef PA_SANITIZER_PRINT_ALL
std::cout << "LifetimeSanitizer - Allocating (copy-construct): " << this << std::endl;
#endif
auto iter = sanitizer_map.find(this);
if (iter == sanitizer_map.end()){
sanitizer_map.insert(this);
return;
}
std::cerr << "LifetimeSanitizer - Double allocation: " << this << std::endl;
std::terminate();
}
void LifetimeSanitizer::operator=(const LifetimeSanitizer& x){
check_usage();
x.check_usage();
}

void LifetimeSanitizer::check_usage() const{
if (!LifetimeSanitizer_enabled.load(std::memory_order_relaxed)){
return;
}

void LifetimeSanitizer::internal_check_usage() const{
if (m_token != SANITIZER_TOKEN || m_self != this){
std::cerr << "Use non-existant: " << this << std::endl;
std::terminate();
terminate_with_dump();
}

if (LifetimeSanitizer_has_been_disabled){
Expand All @@ -171,10 +102,19 @@ void LifetimeSanitizer::check_usage() const{
return;
}
std::cerr << "Use non-existant: " << this << std::endl;
std::terminate();
terminate_with_dump();
}

#endif

PA_NO_INLINE void LifetimeSanitizer::terminate_with_dump(){
// Intentionally crash the program here and let the crash dump deal with
// the error reporting.

std::cerr << (char*)nullptr << std::endl;
}




#endif
}
Loading

0 comments on commit c9c6343

Please sign in to comment.