asan_memory_profile: Fix for deadlock in memory profiler code.
authorSanjeet Karan Singh <ssingh6@ciena.com>
Tue, 4 Apr 2023 22:17:29 +0000 (15:17 -0700)
committerVitaly Buka <vitalybuka@google.com>
Tue, 4 Apr 2023 23:41:44 +0000 (16:41 -0700)
Calling symbolization directly from stopTheWorld was causing deadlock.
For libc dep systems, symbolization uses dl_iterate_phdr, which acquire a
dl write lock. It could deadlock if the lock is already acquired by one of
suspended.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D146990

compiler-rt/lib/asan/asan_memory_profile.cpp

index 6c2b740..3396fc2 100644 (file)
 // This file implements __sanitizer_print_memory_profile.
 //===----------------------------------------------------------------------===//
 
+#include "asan/asan_allocator.h"
+#include "lsan/lsan_common.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
-#include "sanitizer_common/sanitizer_stoptheworld.h"
-#include "lsan/lsan_common.h"
-#include "asan/asan_allocator.h"
 
 #if CAN_SANITIZE_LEAKS
 
@@ -100,19 +99,16 @@ static void ChunkCallback(uptr chunk, void *arg) {
       FindHeapChunkByAllocBeg(chunk));
 }
 
-static void MemoryProfileCB(const SuspendedThreadsList &suspended_threads_list,
-                            void *argument) {
+static void MemoryProfileCB(uptr top_percent, uptr max_number_of_contexts) {
   HeapProfile hp;
+  __lsan::LockAllocator();
   __lsan::ForEachChunk(ChunkCallback, &hp);
-  uptr *Arg = reinterpret_cast<uptr*>(argument);
-  hp.Print(Arg[0], Arg[1]);
+  __lsan::UnlockAllocator();
+  hp.Print(top_percent, max_number_of_contexts);
 
   if (Verbosity())
     __asan_print_accumulated_stats();
 }
-
-#if SANITIZER_LINUX || SANITIZER_NETBSD
-#endif
 }  // namespace __asan
 
 #endif  // CAN_SANITIZE_LEAKS
@@ -122,10 +118,7 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __sanitizer_print_memory_profile(uptr top_percent,
                                       uptr max_number_of_contexts) {
 #if CAN_SANITIZE_LEAKS
-  uptr Arg[2];
-  Arg[0] = top_percent;
-  Arg[1] = max_number_of_contexts;
-  __sanitizer::StopTheWorld(__asan::MemoryProfileCB, Arg);
+  __asan::MemoryProfileCB(top_percent, max_number_of_contexts);
 #endif  // CAN_SANITIZE_LEAKS
 }
 }  // extern "C"