asan_memory_profile: Fix for deadlock in memory profiler code.

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
This commit is contained in:
Sanjeet Karan Singh 2023-04-04 15:17:29 -07:00 committed by Vitaly Buka
parent a78997e0aa
commit 42fc9929ab

View File

@ -11,12 +11,11 @@
// 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"