Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -30,7 +30,6 @@ static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; -static uptr error_message_buffer_size = 0; static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); struct ReportData { @@ -49,17 +48,16 @@ void AppendToErrorMessageBuffer(const char *buffer) { BlockingMutexLock l(&error_message_buf_mutex); if (!error_message_buffer) { - error_message_buffer_size = 1 << 16; error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); + (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__); error_message_buffer_pos = 0; } uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; + RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos); + uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos; internal_strncpy(error_message_buffer + error_message_buffer_pos, buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; + error_message_buffer[kErrorMessageBufferSize - 1] = '\0'; // FIXME: reallocate the buffer instead of truncating the message. error_message_buffer_pos += Min(remaining, length); } @@ -686,13 +684,23 @@ // Print memory stats. if (flags()->print_stats) __asan_print_accumulated_stats(); + + // Copy the message buffer so that we could start logging without holding a + // lock that gets aquired during printing. + InternalScopedBuffer buffer_copy(kErrorMessageBufferSize); { BlockingMutexLock l(&error_message_buf_mutex); - LogFullErrorReport(error_message_buffer); + internal_memcpy(buffer_copy.data(), + error_message_buffer, kErrorMessageBufferSize); + } + + // Remove color sequences since logs cannot print them. + RemoveANSIEscapeSequencesFromString(buffer_copy.data()); + + LogFullErrorReport(buffer_copy.data()); - if (error_report_callback) { - error_report_callback(error_message_buffer); - } + if (error_report_callback) { + error_report_callback(buffer_copy.data()); } CommonSanitizerReportMutex.Unlock(); reporting_thread_tid_ = kInvalidTid; Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -49,6 +49,8 @@ const uptr kMaxThreadStackSize = 1 << 30; // 1Gb +static const uptr kErrorMessageBufferSize = 1 << 16; + // Denotes fake PC values that come from JIT/JAVA/etc. // For such PC values __tsan_symbolize_external() will be called. const u64 kExternalPCBit = 1ULL << 60; @@ -76,7 +78,10 @@ uptr *tls_addr, uptr *tls_size); // Memory management -void *MmapOrDie(uptr size, const char *mem_type); +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false); +INLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) { + return MmapOrDie(size, mem_type, /*raw_report*/ true); +} void UnmapOrDie(void *addr, uptr size); void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr); @@ -310,7 +315,9 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - const char *mmap_type, error_t err); + const char *mmap_type, error_t err, + bool raw_report = false); +void NORETURN RawReportMmapFailureAndDie(); // Set the name of the current thread to 'name', return true on succees. // The name may be truncated to a system-dependent limit. @@ -423,7 +430,7 @@ } INLINE uptr RoundUpTo(uptr size, uptr boundary) { - CHECK(IsPowerOfTwo(boundary)); + RAW_CHECK(IsPowerOfTwo(boundary)); return (size + boundary - 1) & ~(boundary - 1); } @@ -652,9 +659,9 @@ void WriteToSyslog(const char *buffer); #if SANITIZER_MAC -void LogFullErrorReport(const char *error_message_buffer); +void LogFullErrorReport(const char *buffer); #else -INLINE void LogFullErrorReport(const char *error_message_buffer) {} +INLINE void LogFullErrorReport(const char *buffer) {} #endif #if SANITIZER_LINUX || SANITIZER_MAC Index: lib/sanitizer_common/sanitizer_common.cc =================================================================== --- lib/sanitizer_common/sanitizer_common.cc +++ lib/sanitizer_common/sanitizer_common.cc @@ -163,14 +163,19 @@ Die(); } +void NORETURN RawReportMmapFailureAndDie() { + RawWrite("ERROR: Failed to mmap\n"); + Die(); +} + void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - const char *mmap_type, error_t err) { + const char *mmap_type, error_t err, + bool raw_report) { static int recursion_count; - if (recursion_count) { + if (raw_report || recursion_count) { + // If raw report is requested or we went into recursion, just die. // The Report() and CHECK calls below may call mmap recursively and fail. - // If we went into recursion, just die. - RawWrite("ERROR: Failed to mmap\n"); - Die(); + RawReportMmapFailureAndDie(); } recursion_count++; Report("ERROR: %s failed to " Index: lib/sanitizer_common/sanitizer_common_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_common_libcdep.cc +++ lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" -#include "sanitizer_allocator_internal.h" + #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -119,13 +119,14 @@ } } -void WriteToSyslog(const char *buffer) { - char *copy = internal_strdup(buffer); - char *p = copy; +void WriteToSyslog(const char *msg) { + InternalScopedString msg_copy(kErrorMessageBufferSize); + msg_copy.append("%s", msg); + char *p = msg_copy.data(); char *q; // Remove color sequences since syslogs cannot print them. - RemoveANSIEscapeSequencesFromString(copy); + RemoveANSIEscapeSequencesFromString(p); // Print one line at a time. // syslog, at least on Android, has an implicit message length limit. @@ -137,7 +138,6 @@ if (q) p = q + 1; } while (q); - InternalFree(copy); } void MaybeStartBackgroudThread() { Index: lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_mac.cc +++ lib/sanitizer_common/sanitizer_mac.cc @@ -13,6 +13,7 @@ #include "sanitizer_platform.h" #if SANITIZER_MAC +#include "sanitizer_mac.h" // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so // the clients will most certainly use 64-bit ones as well. @@ -25,7 +26,6 @@ #include "sanitizer_flags.h" #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" -#include "sanitizer_mac.h" #include "sanitizer_placement_new.h" #include "sanitizer_platform_limits_posix.h" #include "sanitizer_procmaps.h" Index: lib/sanitizer_common/sanitizer_posix.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix.cc +++ lib/sanitizer_common/sanitizer_posix.cc @@ -112,14 +112,14 @@ #endif // SANITIZER_WORDSIZE } -void *MmapOrDie(uptr size, const char *mem_type) { +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { size = RoundUpTo(size, GetPageSizeCached()); uptr res = internal_mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); int reserrno; if (internal_iserror(res, &reserrno)) - ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report); IncreaseTotalMmap(size); return (void *)res; } Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -83,10 +83,11 @@ } #endif // #if !SANITIZER_GO -void *MmapOrDie(uptr size, const char *mem_type) { +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) - ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError()); + ReportMmapFailureAndDie(size, mem_type, "allocate", + GetLastError(), raw_report); return rv; }