Index: compiler-rt/lib/asan/asan_memory_profile.cpp =================================================================== --- compiler-rt/lib/asan/asan_memory_profile.cpp +++ compiler-rt/lib/asan/asan_memory_profile.cpp @@ -19,6 +19,11 @@ #include "asan/asan_allocator.h" #if CAN_SANITIZE_LEAKS +#include "sanitizer_common/sanitizer_platform.h" + +#if SANITIZER_LINUX || SANITIZER_NETBSD +#include +#endif namespace __asan { @@ -28,6 +33,11 @@ uptr count; }; +struct DoStopTheWorldParam { + StopTheWorldCallback callback; + void *argument; +}; + class HeapProfile { public: HeapProfile() { allocations_.reserve(1024); } @@ -111,6 +121,37 @@ __asan_print_accumulated_stats(); } +static void LockDefStuffAndStopTheWorld(DoStopTheWorldParam *param) { + __lsan::LockThreadRegistry(); + __lsan::LockAllocator(); + __sanitizer::StopTheWorld(param->callback, param->argument); + __lsan::UnlockAllocator(); + __lsan::UnlockThreadRegistry(); +} + +static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info, + size_t size, void *data) { + DoStopTheWorldParam *param = reinterpret_cast(data); + LockDefStuffAndStopTheWorld(param); + return 1; +} + +void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) { + DoStopTheWorldParam param = {callback, argument}; + +#if SANITIZER_LINUX || SANITIZER_NETBSD + // For libc dep systems, Stack depot use dl_iterate_phdr (which acquire a dl + // write lock) + // It could cause deadlock if one of suspended threads aquired that lock and + // haven't released. + // So calling stopTheWorld inside dl_iterate_phdr, first wait for that lock to + // be released (if acquired) + // and than suspend all threads + dl_iterate_phdr(LockStuffAndStopTheWorldCallback, ¶m); +#else + LockDefStuffAndStopTheWorld(¶m); +#endif +} } // namespace __asan #endif // CAN_SANITIZE_LEAKS @@ -123,7 +164,7 @@ uptr Arg[2]; Arg[0] = top_percent; Arg[1] = max_number_of_contexts; - __sanitizer::StopTheWorld(__asan::MemoryProfileCB, Arg); + __asan::LockStuffAndStopTheWorld(__asan::MemoryProfileCB, Arg); #endif // CAN_SANITIZE_LEAKS } } // extern "C"