From 5c25ba3380966ccac5bd0caf2c39bc10c1571e42 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 11 Oct 2024 12:21:18 -0700 Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- compiler-rt/lib/asan/asan_fuchsia.cpp | 3 +- compiler-rt/lib/asan/asan_thread.cpp | 16 ++-- compiler-rt/lib/asan/asan_thread.h | 11 +-- compiler-rt/lib/hwasan/hwasan_thread.cpp | 7 +- compiler-rt/lib/lsan/lsan_common.cpp | 9 ++- compiler-rt/lib/lsan/lsan_common.h | 1 + compiler-rt/lib/lsan/lsan_thread.cpp | 4 + compiler-rt/lib/memprof/memprof_thread.cpp | 9 +-- compiler-rt/lib/memprof/memprof_thread.h | 8 +- .../lib/sanitizer_common/CMakeLists.txt | 1 + .../sanitizer_thread_history.cpp | 73 +++++++++++++++++++ .../sanitizer_thread_history.h | 24 ++++++ .../sanitizer_thread_registry.cpp | 13 +++- .../sanitizer_thread_registry.h | 9 ++- .../tests/sanitizer_thread_registry_test.cpp | 23 ++++-- 15 files changed, 164 insertions(+), 47 deletions(-) create mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp create mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h diff --git a/compiler-rt/lib/asan/asan_fuchsia.cpp b/compiler-rt/lib/asan/asan_fuchsia.cpp index dbc4342e83388c..96c41e9d42ba6a 100644 --- a/compiler-rt/lib/asan/asan_fuchsia.cpp +++ b/compiler-rt/lib/asan/asan_fuchsia.cpp @@ -121,8 +121,7 @@ static AsanThread *CreateAsanThread(StackTrace *stack, u32 parent_tid, // In lieu of AsanThread::Create. AsanThread *thread = (AsanThread *)MmapOrDie(AsanThreadMmapSize(), __func__); - AsanThreadContext::CreateThreadContextArgs args = {thread, stack}; - u32 tid = asanThreadRegistry().CreateThread(0, detached, parent_tid, &args); + u32 tid = asanThreadRegistry().CreateThread(0, detached, parent_tid, thread); asanThreadRegistry().SetThreadName(tid, name); return thread; diff --git a/compiler-rt/lib/asan/asan_thread.cpp b/compiler-rt/lib/asan/asan_thread.cpp index c1a804b9fcccd3..37fb6f2b07f276 100644 --- a/compiler-rt/lib/asan/asan_thread.cpp +++ b/compiler-rt/lib/asan/asan_thread.cpp @@ -21,6 +21,7 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" +#include "sanitizer_common/sanitizer_thread_history.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" namespace __asan { @@ -28,10 +29,7 @@ namespace __asan { // AsanThreadContext implementation. void AsanThreadContext::OnCreated(void *arg) { - CreateThreadContextArgs *args = static_cast(arg); - if (args->stack) - stack_id = StackDepotPut(*args->stack); - thread = args->thread; + thread = static_cast(arg); thread->set_context(this); } @@ -106,8 +104,8 @@ AsanThread *AsanThread::Create(const void *start_data, uptr data_size, CHECK_LE(data_size, availible_size); internal_memcpy(thread->start_data_, start_data, data_size); } - AsanThreadContext::CreateThreadContextArgs args = {thread, stack}; - asanThreadRegistry().CreateThread(0, detached, parent_tid, &args); + asanThreadRegistry().CreateThread(0, detached, parent_tid, + stack ? StackDepotPut(*stack) : 0, thread); return thread; } @@ -558,6 +556,12 @@ void GetRunningThreadsLocked(InternalMmapVector *threads) { threads); } +void PrintThreads() { + InternalScopedString out; + PrintThreadHistory(__asan::asanThreadRegistry(), out); + Report("%s\n", out.data()); +} + } // namespace __lsan // ---------------------- Interface ---------------- {{{1 diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h index 62f1b5337fe4bf..ad9e03d68fe96a 100644 --- a/compiler-rt/lib/asan/asan_thread.h +++ b/compiler-rt/lib/asan/asan_thread.h @@ -36,21 +36,16 @@ class AsanThread; class AsanThreadContext final : public ThreadContextBase { public: explicit AsanThreadContext(int tid) - : ThreadContextBase(tid), announced(false), - destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), + : ThreadContextBase(tid), + announced(false), + destructor_iterations(GetPthreadDestructorIterations()), thread(nullptr) {} bool announced; u8 destructor_iterations; - u32 stack_id; AsanThread *thread; void OnCreated(void *arg) override; void OnFinished() override; - - struct CreateThreadContextArgs { - AsanThread *thread; - StackTrace *stack; - }; }; // AsanThreadContext objects are never freed, so we need many of them. diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cpp b/compiler-rt/lib/hwasan/hwasan_thread.cpp index 3e14a718513d7f..8b32e4e760e2fa 100644 --- a/compiler-rt/lib/hwasan/hwasan_thread.cpp +++ b/compiler-rt/lib/hwasan/hwasan_thread.cpp @@ -218,6 +218,11 @@ void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { __hwasan::hwasanThreadArgRetval().GetAllPtrsLocked(ptrs); } -void GetRunningThreadsLocked(InternalMmapVector *threads) {} +void GetRunningThreadsLocked(InternalMmapVector *threads) { + // TODO: implement. +} +void PrintThreads() { + // TODO: implement. +} } // namespace __lsan diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 6776598651ae9b..b584d1e9723fc8 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -771,11 +771,12 @@ static bool PrintResults(LeakReport &report) { } if (common_flags()->print_suppressions) GetSuppressionContext()->PrintMatchedSuppressions(); - if (unsuppressed_count > 0) { + if (unsuppressed_count) report.PrintSummary(); - return true; - } - return false; + if ((unsuppressed_count && common_flags()->verbosity >= 2) || + flags()->log_threads) + PrintThreads(); + return unsuppressed_count; } static bool CheckForLeaks() { diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index c598b62105873e..f990c7850497a5 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -111,6 +111,7 @@ void GetThreadExtraStackRangesLocked(tid_t os_id, InternalMmapVector *ranges); void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs); void GetRunningThreadsLocked(InternalMmapVector *threads); +void PrintThreads(); //// -------------------------------------------------------------------------- //// Allocator prototypes. diff --git a/compiler-rt/lib/lsan/lsan_thread.cpp b/compiler-rt/lib/lsan/lsan_thread.cpp index 07c7b923623fa9..9e481e97ac4731 100644 --- a/compiler-rt/lib/lsan/lsan_thread.cpp +++ b/compiler-rt/lib/lsan/lsan_thread.cpp @@ -109,6 +109,10 @@ void GetRunningThreadsLocked(InternalMmapVector *threads) { threads); } +void PrintThreads() { + // TODO: implement. +} + void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { GetThreadArgRetval().GetAllPtrsLocked(ptrs); } diff --git a/compiler-rt/lib/memprof/memprof_thread.cpp b/compiler-rt/lib/memprof/memprof_thread.cpp index 50072bb91ee74c..4b9665ffc3fcea 100644 --- a/compiler-rt/lib/memprof/memprof_thread.cpp +++ b/compiler-rt/lib/memprof/memprof_thread.cpp @@ -25,10 +25,7 @@ namespace __memprof { // MemprofThreadContext implementation. void MemprofThreadContext::OnCreated(void *arg) { - CreateThreadContextArgs *args = static_cast(arg); - if (args->stack) - stack_id = StackDepotPut(*args->stack); - thread = args->thread; + thread = static_cast(arg); thread->set_context(this); } @@ -79,8 +76,8 @@ MemprofThread *MemprofThread::Create(thread_callback_t start_routine, void *arg, MemprofThread *thread = (MemprofThread *)MmapOrDie(size, __func__); thread->start_routine_ = start_routine; thread->arg_ = arg; - MemprofThreadContext::CreateThreadContextArgs args = {thread, stack}; - memprofThreadRegistry().CreateThread(0, detached, parent_tid, &args); + memprofThreadRegistry().CreateThread( + 0, detached, parent_tid, stack ? StackDepotPut(*stack) : 0, thread); return thread; } diff --git a/compiler-rt/lib/memprof/memprof_thread.h b/compiler-rt/lib/memprof/memprof_thread.h index 4c9313fcb369eb..fb90dbf328a430 100644 --- a/compiler-rt/lib/memprof/memprof_thread.h +++ b/compiler-rt/lib/memprof/memprof_thread.h @@ -34,20 +34,14 @@ class MemprofThread; struct MemprofThreadContext final : public ThreadContextBase { explicit MemprofThreadContext(int tid) : ThreadContextBase(tid), announced(false), - destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), + destructor_iterations(GetPthreadDestructorIterations()), thread(nullptr) {} bool announced; u8 destructor_iterations; - u32 stack_id; MemprofThread *thread; void OnCreated(void *arg) override; void OnFinished() override; - - struct CreateThreadContextArgs { - MemprofThread *thread; - StackTrace *stack; - }; }; // MemprofThreadContext objects are never freed, so we need many of them. diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index 556a64f3017488..09391e4f5f3704 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -94,6 +94,7 @@ set(SANITIZER_SYMBOLIZER_SOURCES sanitizer_symbolizer_report.cpp sanitizer_symbolizer_report_fuchsia.cpp sanitizer_symbolizer_win.cpp + sanitizer_thread_history.cpp sanitizer_unwind_linux_libcdep.cpp sanitizer_unwind_fuchsia.cpp sanitizer_unwind_win.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp new file mode 100644 index 00000000000000..6a4d9bf231811f --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp @@ -0,0 +1,73 @@ +//===-- sanitizer_thread_history.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_thread_history.h" + +#include "sanitizer_stackdepot.h" +namespace __sanitizer { + +void PrintThreadHistory(ThreadRegistry ®istry, InternalScopedString &out) { + ThreadRegistryLock l(®istry); + // Stack traces are largest part of printout and they often the same for + // multiple threads, so we will deduplicate them. + InternalMmapVector stacks; + + registry.RunCallbackForEachThreadLocked( + [](ThreadContextBase *context, void *arg) { + static_cast(arg)->push_back(context); + }, + &stacks); + + Sort(stacks.data(), stacks.size(), + [](const ThreadContextBase *a, const ThreadContextBase *b) { + if (a->stack_id < b->stack_id) + return true; + if (a->stack_id > b->stack_id) + return false; + return a->tid < b->tid; + }); + + auto describe_thread = [&](const ThreadContextBase *context) { + if (!context) { + out.Append("T-1"); + return; + } + out.AppendF("T%llu/%llu", context->unique_id, context->os_id); + if (internal_strlen(context->name)) + out.AppendF(" (%s)", context->name); + }; + + auto get_parent = + [&](const ThreadContextBase *context) -> const ThreadContextBase * { + if (!context) + return nullptr; + ThreadContextBase *parent = registry.GetThreadLocked(context->parent_tid); + if (!parent) + return nullptr; + if (parent->unique_id >= context->unique_id) + return nullptr; + return parent; + }; + + const ThreadContextBase *prev = nullptr; + for (const ThreadContextBase *context : stacks) { + if (prev->stack_id != context->stack_id) { + StackDepotGet(prev->stack_id).PrintTo(&out); + prev = context; + } + out.Append("Thread "); + describe_thread(context); + out.Append(" was created by "); + describe_thread(get_parent(context)); + out.Append("\n"); + } + if (prev) + StackDepotGet(prev->stack_id).PrintTo(&out); +} + +} // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h b/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h new file mode 100644 index 00000000000000..2995f6015fe50e --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h @@ -0,0 +1,24 @@ +//===-- sanitizer_thread_history.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Utility to print thread histroy from ThreadRegistry. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_THREAD_HISTORY_H +#define SANITIZER_THREAD_HISTORY_H + +#include "sanitizer_thread_registry.h" + +namespace __sanitizer { + +void PrintThreadHistory(ThreadRegistry& registry, InternalScopedString& out); + +} // namespace __sanitizer + +#endif // SANITIZER_THREAD_HISTORY_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp index df04822b28851c..cdc24f4a8869c7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp @@ -27,6 +27,7 @@ ThreadContextBase::ThreadContextBase(u32 tid) detached(false), thread_type(ThreadType::Regular), parent_tid(0), + stack_id(0), next(0) { name[0] = '\0'; atomic_store(&thread_destroyed, 0, memory_order_release); @@ -88,14 +89,17 @@ void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type, } void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id, - bool _detached, u32 _parent_tid, void *arg) { + bool _detached, u32 _parent_tid, + u32 _stack_tid, void *arg) { status = ThreadStatusCreated; user_id = _user_id; unique_id = _unique_id; detached = _detached; // Parent tid makes no sense for the main thread. - if (tid != kMainTid) + if (tid != kMainTid) { parent_tid = _parent_tid; + stack_id = _stack_tid; + } OnCreated(arg); } @@ -143,7 +147,7 @@ uptr ThreadRegistry::GetMaxAliveThreads() { } u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, - void *arg) { + u32 stack_tid, void *arg) { ThreadRegistryLock l(this); u32 tid = kInvalidTid; ThreadContextBase *tctx = QuarantinePop(); @@ -181,7 +185,8 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, // positives later (e.g. if we join a wrong thread). CHECK(live_.try_emplace(user_id, tid).second); } - tctx->SetCreated(user_id, total_threads_++, detached, parent_tid, arg); + tctx->SetCreated(user_id, total_threads_++, detached, parent_tid, stack_tid, + arg); return tid; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h b/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h index bf492c17f7e107..e06abb3932da5c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h @@ -52,6 +52,7 @@ class ThreadContextBase { ThreadType thread_type; u32 parent_tid; + u32 stack_id; ThreadContextBase *next; // For storing thread contexts in a list. atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished @@ -63,7 +64,7 @@ class ThreadContextBase { void SetFinished(); void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg); void SetCreated(uptr _user_id, u64 _unique_id, bool _detached, - u32 _parent_tid, void *arg); + u32 _parent_tid, u32 _stack_tid, void *arg); void Reset(); void SetDestroyed(); @@ -106,7 +107,11 @@ class SANITIZER_MUTEX ThreadRegistry { u32 NumThreadsLocked() const { return threads_.size(); } - u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg); + u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, u32 stack_tid, + void *arg); + u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg) { + return CreateThread(user_id, detached, parent_tid, 0, arg); + } typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg); // Invokes callback with a specified arg for each thread context. diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp index 8c4b4ba5c58f7d..c3cac707f0a0b3 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp @@ -64,11 +64,12 @@ static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) { static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { // Create and start a main thread. - EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0)); + EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0, nullptr)); registry->StartThread(0, 0, ThreadType::Regular, 0); // Create a bunch of threads. for (u32 i = 1; i <= 10; i++) { - EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); + EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 100 + i, + 200 + i, nullptr)); } CheckThreadQuantity(registry, 11, 1, 11); // Start some of them. @@ -88,19 +89,27 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { std::vector new_tids; for (u32 i = 11; i <= 15; i++) { new_tids.push_back( - registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); + registry->CreateThread(get_uid(i), is_detached(i), 0, 0, nullptr)); } ASSERT_LE(kRegistryQuarantine, 5U); - u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine : 0); + u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine : 0); CheckThreadQuantity(registry, exp_total, 6, 11); // Test SetThreadName and FindThread. registry->SetThreadName(6, "six"); registry->SetThreadName(7, "seven"); - EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven")); + EXPECT_EQ(7U, registry->FindThread(HasName, (void *)"seven")); EXPECT_EQ(kInvalidTid, registry->FindThread(HasName, (void *)"none")); - EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0))); - EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10))); + EXPECT_EQ(0U, registry->FindThread(HasUid, (void *)get_uid(0))); + EXPECT_EQ(10U, registry->FindThread(HasUid, (void *)get_uid(10))); EXPECT_EQ(kInvalidTid, registry->FindThread(HasUid, (void *)0x1234)); + EXPECT_EQ(7U, + registry->FindThread([](ThreadContextBase *tctx, + void *) { return tctx->parent_tid == 107; }, + nullptr)); + EXPECT_EQ(8U, + registry->FindThread([](ThreadContextBase *tctx, + void *) { return tctx->stack_id == 208; }, + nullptr)); // Detach and finish and join remaining threads. for (u32 i = 6; i <= 10; i++) { registry->DetachThread(i, 0); From abee2b641366897f8905ac61c49ac70d2a4d2a99 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 11 Oct 2024 12:43:17 -0700 Subject: [PATCH 2/4] format Created using spr 1.3.4 --- compiler-rt/lib/lsan/lsan_common.cpp | 3 +-- compiler-rt/lib/lsan/lsan_flags.inc | 3 ++- compiler-rt/test/lsan/TestCases/flag_retries.c | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 8ed2cfc63cbae9..c53e1e610054bf 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -833,8 +833,7 @@ static bool CheckForLeaksOnce() { static bool CheckForLeaks() { int with_leaks = 0; - for (int i = 0; i < flags()->retries; ++i) - with_leaks += CheckForLeaksOnce(); + for (int i = 0; i < flags()->retries; ++i) with_leaks += CheckForLeaksOnce(); return with_leaks == flags()->retries; } diff --git a/compiler-rt/lib/lsan/lsan_flags.inc b/compiler-rt/lib/lsan/lsan_flags.inc index 59edc0baa77d85..ae6057f171b825 100644 --- a/compiler-rt/lib/lsan/lsan_flags.inc +++ b/compiler-rt/lib/lsan/lsan_flags.inc @@ -43,7 +43,8 @@ LSAN_FLAG(bool, use_poisoned, false, "Consider pointers found in poisoned memory to be valid.") LSAN_FLAG(bool, log_pointers, false, "Debug logging") LSAN_FLAG(bool, log_threads, false, "Debug logging") -LSAN_FLAG(int, retries, 1, "Debug option to repeat leak checking multiple times") +LSAN_FLAG(int, retries, 1, + "Debug option to repeat leak checking multiple times") LSAN_FLAG(const char *, suppressions, "", "Suppressions file name.") LSAN_FLAG(int, thread_suspend_fail, 1, "Behaviour if thread suspendion all thread (0 - " diff --git a/compiler-rt/test/lsan/TestCases/flag_retries.c b/compiler-rt/test/lsan/TestCases/flag_retries.c index 3891a47bb0a566..de814bcab446c5 100644 --- a/compiler-rt/test/lsan/TestCases/flag_retries.c +++ b/compiler-rt/test/lsan/TestCases/flag_retries.c @@ -4,20 +4,20 @@ // RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0:retries=12 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK12 #include +#include #include #include #include -#include void *p; int main(int argc, char *argv[]) { fprintf(stderr, "Test alloc: %p.\n", malloc(1337)); -// CHECK: Test alloc: + // CHECK: Test alloc: assert(__lsan_do_recoverable_leak_check() == 1); -// CHECK1-COUNT-1: SUMMARY: {{.*}}Sanitizer: 1337 byte -// CHECK12-COUNT-12: SUMMARY: {{.*}}Sanitizer: 1337 byte + // CHECK1-COUNT-1: SUMMARY: {{.*}}Sanitizer: 1337 byte + // CHECK12-COUNT-12: SUMMARY: {{.*}}Sanitizer: 1337 byte _exit(0); } From 7a0b416c87601910e51525d5481f8921fd5eb31a Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 11 Oct 2024 14:39:29 -0700 Subject: [PATCH 3/4] tries Created using spr 1.3.4 --- compiler-rt/lib/lsan/lsan_common.cpp | 6 +++--- compiler-rt/lib/lsan/lsan_flags.inc | 3 +-- .../test/lsan/TestCases/{flag_retries.c => flag_tries.c} | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) rename compiler-rt/test/lsan/TestCases/{flag_retries.c => flag_tries.c} (90%) diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index c53e1e610054bf..c05e0dd0a9332d 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -832,9 +832,9 @@ static bool CheckForLeaksOnce() { } static bool CheckForLeaks() { - int with_leaks = 0; - for (int i = 0; i < flags()->retries; ++i) with_leaks += CheckForLeaksOnce(); - return with_leaks == flags()->retries; + int leaking_tries = 0; + for (int i = 0; i < flags()->tries; ++i) leaking_tries += CheckForLeaksOnce(); + return leaking_tries == flags()->tries; } static bool has_reported_leaks = false; diff --git a/compiler-rt/lib/lsan/lsan_flags.inc b/compiler-rt/lib/lsan/lsan_flags.inc index ae6057f171b825..c97b021ba5c02f 100644 --- a/compiler-rt/lib/lsan/lsan_flags.inc +++ b/compiler-rt/lib/lsan/lsan_flags.inc @@ -43,8 +43,7 @@ LSAN_FLAG(bool, use_poisoned, false, "Consider pointers found in poisoned memory to be valid.") LSAN_FLAG(bool, log_pointers, false, "Debug logging") LSAN_FLAG(bool, log_threads, false, "Debug logging") -LSAN_FLAG(int, retries, 1, - "Debug option to repeat leak checking multiple times") +LSAN_FLAG(int, tries, 1, "Debug option to repeat leak checking multiple times") LSAN_FLAG(const char *, suppressions, "", "Suppressions file name.") LSAN_FLAG(int, thread_suspend_fail, 1, "Behaviour if thread suspendion all thread (0 - " diff --git a/compiler-rt/test/lsan/TestCases/flag_retries.c b/compiler-rt/test/lsan/TestCases/flag_tries.c similarity index 90% rename from compiler-rt/test/lsan/TestCases/flag_retries.c rename to compiler-rt/test/lsan/TestCases/flag_tries.c index de814bcab446c5..d6af766d5ef282 100644 --- a/compiler-rt/test/lsan/TestCases/flag_retries.c +++ b/compiler-rt/test/lsan/TestCases/flag_tries.c @@ -1,7 +1,7 @@ // Test retries option of lsan. // RUN: %clang_lsan %s -o %t // RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0 %run %t foo 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK1 -// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0:retries=12 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK12 +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0:tries=12 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK12 #include #include From e4752d63c55af5947e0669961f34cc6da6ffa8e7 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 11 Oct 2024 16:29:30 -0700 Subject: [PATCH 4/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20introduced=20through=20rebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- compiler-rt/lib/asan/asan_thread.cpp | 7 -- compiler-rt/lib/hwasan/hwasan_thread.cpp | 7 +- compiler-rt/lib/lsan/lsan_common.cpp | 9 ++- compiler-rt/lib/lsan/lsan_common.h | 1 - compiler-rt/lib/lsan/lsan_thread.cpp | 4 -- .../lib/sanitizer_common/CMakeLists.txt | 1 - .../sanitizer_thread_history.cpp | 72 ------------------- .../sanitizer_thread_history.h | 24 ------- .../tests/sanitizer_thread_registry_test.cpp | 60 ---------------- 9 files changed, 5 insertions(+), 180 deletions(-) delete mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp delete mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h diff --git a/compiler-rt/lib/asan/asan_thread.cpp b/compiler-rt/lib/asan/asan_thread.cpp index 37fb6f2b07f276..0779daa107682b 100644 --- a/compiler-rt/lib/asan/asan_thread.cpp +++ b/compiler-rt/lib/asan/asan_thread.cpp @@ -21,7 +21,6 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" -#include "sanitizer_common/sanitizer_thread_history.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" namespace __asan { @@ -556,12 +555,6 @@ void GetRunningThreadsLocked(InternalMmapVector *threads) { threads); } -void PrintThreads() { - InternalScopedString out; - PrintThreadHistory(__asan::asanThreadRegistry(), out); - Report("%s\n", out.data()); -} - } // namespace __lsan // ---------------------- Interface ---------------- {{{1 diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cpp b/compiler-rt/lib/hwasan/hwasan_thread.cpp index 8b32e4e760e2fa..3e14a718513d7f 100644 --- a/compiler-rt/lib/hwasan/hwasan_thread.cpp +++ b/compiler-rt/lib/hwasan/hwasan_thread.cpp @@ -218,11 +218,6 @@ void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { __hwasan::hwasanThreadArgRetval().GetAllPtrsLocked(ptrs); } -void GetRunningThreadsLocked(InternalMmapVector *threads) { - // TODO: implement. -} -void PrintThreads() { - // TODO: implement. -} +void GetRunningThreadsLocked(InternalMmapVector *threads) {} } // namespace __lsan diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index b584d1e9723fc8..6776598651ae9b 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -771,12 +771,11 @@ static bool PrintResults(LeakReport &report) { } if (common_flags()->print_suppressions) GetSuppressionContext()->PrintMatchedSuppressions(); - if (unsuppressed_count) + if (unsuppressed_count > 0) { report.PrintSummary(); - if ((unsuppressed_count && common_flags()->verbosity >= 2) || - flags()->log_threads) - PrintThreads(); - return unsuppressed_count; + return true; + } + return false; } static bool CheckForLeaks() { diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index f990c7850497a5..c598b62105873e 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -111,7 +111,6 @@ void GetThreadExtraStackRangesLocked(tid_t os_id, InternalMmapVector *ranges); void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs); void GetRunningThreadsLocked(InternalMmapVector *threads); -void PrintThreads(); //// -------------------------------------------------------------------------- //// Allocator prototypes. diff --git a/compiler-rt/lib/lsan/lsan_thread.cpp b/compiler-rt/lib/lsan/lsan_thread.cpp index 9e481e97ac4731..07c7b923623fa9 100644 --- a/compiler-rt/lib/lsan/lsan_thread.cpp +++ b/compiler-rt/lib/lsan/lsan_thread.cpp @@ -109,10 +109,6 @@ void GetRunningThreadsLocked(InternalMmapVector *threads) { threads); } -void PrintThreads() { - // TODO: implement. -} - void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { GetThreadArgRetval().GetAllPtrsLocked(ptrs); } diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index 09391e4f5f3704..556a64f3017488 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -94,7 +94,6 @@ set(SANITIZER_SYMBOLIZER_SOURCES sanitizer_symbolizer_report.cpp sanitizer_symbolizer_report_fuchsia.cpp sanitizer_symbolizer_win.cpp - sanitizer_thread_history.cpp sanitizer_unwind_linux_libcdep.cpp sanitizer_unwind_fuchsia.cpp sanitizer_unwind_win.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp deleted file mode 100644 index 0f5bec3ca083e3..00000000000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//===-- sanitizer_thread_history.cpp --------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_thread_history.h" - -#include "sanitizer_stackdepot.h" -namespace __sanitizer { - -void PrintThreadHistory(ThreadRegistry ®istry, InternalScopedString &out) { - ThreadRegistryLock l(®istry); - // Stack traces are largest part of printout and they often the same for - // multiple threads, so we will deduplicate them. - InternalMmapVector stacks; - - registry.RunCallbackForEachThreadLocked( - [](ThreadContextBase *context, void *arg) { - static_cast(arg)->push_back(context); - }, - &stacks); - - Sort(stacks.data(), stacks.size(), - [](const ThreadContextBase *a, const ThreadContextBase *b) { - if (a->stack_id < b->stack_id) - return true; - if (a->stack_id > b->stack_id) - return false; - return a->unique_id < b->unique_id; - }); - - auto describe_thread = [&](const ThreadContextBase *context) { - if (!context) { - out.Append("T-1"); - return; - } - out.AppendF("T%llu/%llu", context->unique_id, context->os_id); - if (internal_strlen(context->name)) - out.AppendF(" (%s)", context->name); - }; - - auto get_parent = - [&](const ThreadContextBase *context) -> const ThreadContextBase * { - if (!context) - return nullptr; - ThreadContextBase *parent = registry.GetThreadLocked(context->parent_tid); - if (!parent) - return nullptr; - if (parent->unique_id >= context->unique_id) - return nullptr; - return parent; - }; - - const ThreadContextBase *prev = nullptr; - for (const ThreadContextBase *context : stacks) { - if (prev && prev->stack_id != context->stack_id) - StackDepotGet(prev->stack_id).PrintTo(&out); - prev = context; - out.Append("Thread "); - describe_thread(context); - out.Append(" was created by "); - describe_thread(get_parent(context)); - out.Append("\n"); - } - if (prev) - StackDepotGet(prev->stack_id).PrintTo(&out); -} - -} // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h b/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h deleted file mode 100644 index 2995f6015fe50e..00000000000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- sanitizer_thread_history.h ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Utility to print thread histroy from ThreadRegistry. -// -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_THREAD_HISTORY_H -#define SANITIZER_THREAD_HISTORY_H - -#include "sanitizer_thread_registry.h" - -namespace __sanitizer { - -void PrintThreadHistory(ThreadRegistry& registry, InternalScopedString& out); - -} // namespace __sanitizer - -#endif // SANITIZER_THREAD_HISTORY_H diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp index 6e84ecdfeba683..c3cac707f0a0b3 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cpp @@ -11,19 +11,11 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_thread_registry.h" -#include #include -#include "gmock/gmock.h" #include "gtest/gtest.h" -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_stackdepot.h" -#include "sanitizer_common/sanitizer_stacktrace.h" -#include "sanitizer_common/sanitizer_thread_history.h" #include "sanitizer_pthread_wrappers.h" -using testing::HasSubstr; - namespace __sanitizer { static Mutex tctx_allocator_lock; @@ -247,56 +239,4 @@ TEST(SanitizerCommon, ThreadRegistryThreadedTest) { ThreadedTestRegistry(®istry); } -TEST(SanitizerCommon, PrintThreadHistory) { - ThreadRegistry registry(GetThreadContext, - kThreadsPerShard * kNumShards + 1, 10, 0); - - UNINITIALIZED BufferedStackTrace stack1; - stack1.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, false, - /*max_depth=*/1); - - UNINITIALIZED BufferedStackTrace stack2; - stack2.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, false, - /*max_depth=*/1); - - EXPECT_EQ(0U, registry.CreateThread(0, true, -1, 0, nullptr)); - for (int i = 0; i < 5; i++) { - registry.CreateThread(0, true, 0, StackDepotPut(stack1), nullptr); - registry.CreateThread(0, true, 0, StackDepotPut(stack2), nullptr); - } - - InternalScopedString out; - PrintThreadHistory(registry, out); - - std::string substrings[] = { - "Thread T0/0 was created by T-1", - "", - "", - "Thread T1/0 was created by T0/0", - "Thread T3/0 was created by T0/0", - "Thread T5/0 was created by T0/0", - "Thread T7/0 was created by T0/0", - "Thread T9/0 was created by T0/0", - "#0 0x", - "", - "Thread T2/0 was created by T0/0", - "Thread T4/0 was created by T0/0", - "Thread T6/0 was created by T0/0", - "Thread T8/0 was created by T0/0", - "Thread T10/0 was created by T0/0", - "#0 0x", - "", - }; - - std::stringstream ss(out.data()); - std::string line; - - for (auto substr : substrings) { - std::getline(ss, line); - EXPECT_THAT(line, HasSubstr(substr)) << line; - } - - EXPECT_FALSE(std::getline(ss, line)) << "Unmatched line: " << line; -} - } // namespace __sanitizer