Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -49,13 +49,13 @@ void AppendToErrorMessageBuffer(const char *buffer) { BlockingMutexLock l(&error_message_buf_mutex); if (!error_message_buffer) { - error_message_buffer_size = 1 << 16; + error_message_buffer_size = ErrorMessageBufferSize; error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); + (char*)MmapOrDieQuietly(error_message_buffer_size, __func__); error_message_buffer_pos = 0; } uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); + RAW_CHECK(error_message_buffer_size >= error_message_buffer_pos); uptr remaining = error_message_buffer_size - error_message_buffer_pos; internal_strncpy(error_message_buffer + error_message_buffer_pos, buffer, remaining); @@ -686,13 +686,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(error_message_buffer_size); { BlockingMutexLock l(&error_message_buf_mutex); - LogFullErrorReport(error_message_buffer); + internal_memcpy(buffer_copy.data(), + error_message_buffer, error_message_buffer_size); + } + + // Remove color sequences since logs cannot print them. + RemoveANSIEscapeSequencesFromString(buffer_copy.data()); + + LogFullErrorReport(&buffer_copy); - 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 ErrorMessageBufferSize = 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); @@ -311,6 +316,7 @@ 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); +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 +429,7 @@ } INLINE uptr RoundUpTo(uptr size, uptr boundary) { - CHECK(IsPowerOfTwo(boundary)); + RAW_CHECK(IsPowerOfTwo(boundary)); return (size + boundary - 1) & ~(boundary - 1); } @@ -652,9 +658,9 @@ void WriteToSyslog(const char *buffer); #if SANITIZER_MAC -void LogFullErrorReport(const char *error_message_buffer); +void LogFullErrorReport(InternalScopedBuffer *buffer); #else -INLINE void LogFullErrorReport(const char *error_message_buffer) {} +INLINE void LogFullErrorReport(InternalScopedBuffer *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,18 @@ 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) { static int recursion_count; if (recursion_count) { // 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,6 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" -#include "sanitizer_allocator_internal.h" #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -119,13 +118,14 @@ } } -void WriteToSyslog(const char *buffer) { - char *copy = internal_strdup(buffer); - char *p = copy; +void WriteToSyslog(const char *msg) { + InternalScopedString msg_copy(ErrorMessageBufferSize); + 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 +137,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" @@ -399,7 +399,7 @@ asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); } -void LogFullErrorReport(const char *buffer) { +void LogFullErrorReport(InternalScopedBuffer *buffer) { // Log with os_trace. This will make it into the crash log. #if SANITIZER_OS_TRACE if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) { @@ -430,7 +430,7 @@ // pthread_create wrapper needs to acquire the lock as well. BlockingMutexLock l(&syslog_lock); if (common_flags()->log_to_syslog) - WriteToSyslog(buffer); + WriteToSyslog(buffer->data()); } void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { Index: lib/sanitizer_common/sanitizer_posix.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix.cc +++ lib/sanitizer_common/sanitizer_posix.cc @@ -112,14 +112,18 @@ #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); + if (internal_iserror(res, &reserrno)) { + if (raw_report) + RawReportMmapFailureAndDie(); + else + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); + } 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,14 @@ } #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()); + if (rv == 0) { + if (raw_report) + RawReportMmapFailureAndDie(); + else + ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError()); + } return rv; }