Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -51,11 +51,11 @@ if (!error_message_buffer) { error_message_buffer_size = 1 << 16; 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); @@ -670,13 +670,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); + } - if (error_report_callback) { - error_report_callback(error_message_buffer); - } + // Remove color sequences since logs cannot print them. + RemoveANSIEscapeSequencesFromString(buffer_copy.data()); + + LogFullErrorReport(&buffer_copy); + + if (error_report_callback) { + error_report_callback(buffer_copy.data()); } Report("ABORTING\n"); Die(); Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -76,7 +76,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 +314,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 +427,7 @@ } INLINE uptr RoundUpTo(uptr size, uptr boundary) { - CHECK(IsPowerOfTwo(boundary)); + RAW_CHECK(IsPowerOfTwo(boundary)); return (size + boundary - 1) & ~(boundary - 1); } @@ -649,12 +653,12 @@ ANDROID_POST_LOLLIPOP = 23 }; -void WriteToSyslog(const char *buffer); +void WriteToSyslog(InternalScopedBuffer *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,12 @@ } } -void WriteToSyslog(const char *buffer) { - char *copy = internal_strdup(buffer); - char *p = copy; +void WriteToSyslog(InternalScopedBuffer *buffer) { + char *p = buffer->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 +135,6 @@ if (q) p = q + 1; } while (q); - InternalFree(copy); } void MaybeStartBackgroudThread() { Index: lib/sanitizer_common/sanitizer_common_nolibc.cc =================================================================== --- lib/sanitizer_common/sanitizer_common_nolibc.cc +++ lib/sanitizer_common/sanitizer_common_nolibc.cc @@ -20,7 +20,7 @@ #if SANITIZER_LINUX bool ShouldLogAfterPrintf() { return false; } #endif -void WriteToSyslog(const char *buffer) {} +void WriteToSyslog(InternalScopedBuffer *buffer) {} void Abort() { internal__exit(1); } } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_mac.cc +++ lib/sanitizer_common/sanitizer_mac.cc @@ -380,7 +380,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 (GetMacosVersion() >= MACOS_VERSION_MAVERICKS) { // os_trace requires the message (format parameter) to be a string literal. 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_printf.cc =================================================================== --- lib/sanitizer_common/sanitizer_printf.cc +++ lib/sanitizer_common/sanitizer_printf.cc @@ -278,8 +278,11 @@ # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) - WriteToSyslog(buffer); + if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) { + InternalScopedBuffer buffer_copy(buffer_size); + internal_memcpy(buffer_copy.data(), buffer, buffer_size); + WriteToSyslog(&buffer_copy); + } CallPrintfAndReportCallback(buffer); // If we had mapped any memory, clean up. if (buffer != local_buffer) 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; }