summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2017-09-22 18:32:05 +0000
committerVitaly Buka <vitalybuka@google.com>2017-09-22 18:32:05 +0000
commit13b2b2b8855fd5eadff25fc0a1a9e54152154557 (patch)
treeea9372709ed50246250892a48f09c8f936a49835 /lib
parent106ad97baa50902f586a3b513fab86760ad73705 (diff)
[sanitizer] Move report locking code from asan into common
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@314008 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/asan/asan_report.cc55
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc36
-rw-r--r--lib/sanitizer_common/sanitizer_common.h8
3 files changed, 55 insertions, 44 deletions
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index d832633db..9536ead66 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -125,34 +125,16 @@ class ScopedInErrorReport {
static const u32 kUnclaimedTid = 0xfffffe;
static_assert(kUnclaimedTid != kInvalidTid, "Must be different");
- explicit ScopedInErrorReport(bool fatal = false) {
- halt_on_error_ = fatal || flags()->halt_on_error;
- u32 current_tid = GetCurrentTidOrInvalid();
-
- for (;;) {
- u32 expected_tid = kUnclaimedTid;
- if (atomic_compare_exchange_strong(&reporting_thread_tid_, &expected_tid,
- current_tid, memory_order_relaxed)) {
- // We've claimed reporting_thread_tid_ so proceed.
- StartReporting();
- return;
- }
-
- if (expected_tid == current_tid) {
- // This is either asynch signal or nested error during error reporting.
- // Fail simple to avoid deadlocks in Report().
-
- // Can't use Report() here because of potential deadlocks in nested
- // signal handlers.
- static const char msg[] =
- "AddressSanitizer: nested bug in the same thread, aborting.\n";
- CatastrophicErrorWrite(msg, sizeof(msg) - 1);
-
- internal__exit(common_flags()->exitcode);
- }
-
- SleepForMillis(100);
- }
+ explicit ScopedInErrorReport(bool fatal = false)
+ : error_report_lock_(GetCurrentTidOrInvalid()),
+ halt_on_error_(fatal || flags()->halt_on_error) {
+ // Make sure the registry and sanitizer report mutexes are locked while
+ // we're printing an error report.
+ // We can lock them only here to avoid self-deadlock in case of
+ // recursive reports.
+ asanThreadRegistry().Lock();
+ Printf(
+ "=================================================================\n");
}
~ScopedInErrorReport() {
@@ -204,9 +186,6 @@ class ScopedInErrorReport {
Report("ABORTING\n");
Die();
}
-
- CommonSanitizerReportMutex.Unlock();
- atomic_store_relaxed(&reporting_thread_tid_, kUnclaimedTid);
}
void ReportError(const ErrorDescription &description) {
@@ -220,25 +199,13 @@ class ScopedInErrorReport {
}
private:
- void StartReporting() {
- CommonSanitizerReportMutex.Lock();
- // Make sure the registry and sanitizer report mutexes are locked while
- // we're printing an error report.
- // We can lock them only here to avoid self-deadlock in case of
- // recursive reports.
- asanThreadRegistry().Lock();
- Printf(
- "=================================================================\n");
- }
-
- static atomic_uint32_t reporting_thread_tid_;
+ ScopedErrorReportLock error_report_lock_;
// Error currently being reported. This enables the destructor to interact
// with the debugger and point it to an error description.
static ErrorDescription current_error_;
bool halt_on_error_;
};
-atomic_uint32_t ScopedInErrorReport::reporting_thread_tid_ = {kUnclaimedTid};
ErrorDescription ScopedInErrorReport::current_error_;
void ReportDeadlySignal(const SignalContext &sig) {
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 970b11c00..c31f4e3a6 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/lib/sanitizer_common/sanitizer_common.cc
@@ -348,6 +348,42 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
return 0;
}
+static const u32 kUnclaimedTid = 0xfffffe;
+static atomic_uint32_t reporting_thread_tid = {kUnclaimedTid};
+
+ScopedErrorReportLock::ScopedErrorReportLock(u32 current_tid) {
+ for (;;) {
+ u32 expected_tid = kUnclaimedTid;
+ if (current_tid == kUnclaimedTid ||
+ atomic_compare_exchange_strong(&reporting_thread_tid, &expected_tid,
+ current_tid, memory_order_relaxed)) {
+ // We've claimed reporting_thread_tid_ so proceed.
+ CommonSanitizerReportMutex.Lock();
+ return;
+ }
+
+ if (expected_tid == current_tid) {
+ // This is either asynch signal or nested error during error reporting.
+ // Fail simple to avoid deadlocks in Report().
+
+ // Can't use Report() here because of potential deadlocks in nested
+ // signal handlers.
+ static const char msg[] =
+ "AddressSanitizer: nested bug in the same thread, aborting.\n";
+ CatastrophicErrorWrite(msg, sizeof(msg) - 1);
+
+ internal__exit(common_flags()->exitcode);
+ }
+
+ internal_sched_yield();
+ }
+}
+
+ScopedErrorReportLock::~ScopedErrorReportLock() {
+ CommonSanitizerReportMutex.Unlock();
+ atomic_store_relaxed(&reporting_thread_tid, kUnclaimedTid);
+}
+
} // namespace __sanitizer
using namespace __sanitizer; // NOLINT
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index 75508cbe4..e2e2224d4 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -205,8 +205,16 @@ void SetPrintfAndReportCallback(void (*callback)(const char *));
} while (0)
// Can be used to prevent mixing error reports from different sanitizers.
+// FIXME: Replace with ScopedErrorReportLock and hide.
extern StaticSpinMutex CommonSanitizerReportMutex;
+// Lock sanitizer error reporting and protects against nested errors.
+class ScopedErrorReportLock {
+ public:
+ explicit ScopedErrorReportLock(u32 current_tid);
+ ~ScopedErrorReportLock();
+};
+
extern uptr stoptheworld_tracer_pid;
extern uptr stoptheworld_tracer_ppid;