[compiler-rt] [lsan] Add debug option to "deflake" leaks (PR #112037)
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 11 16:30:05 PDT 2024
https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/112037
>From 5c25ba3380966ccac5bd0caf2c39bc10c1571e42 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
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<CreateThreadContextArgs *>(arg);
- if (args->stack)
- stack_id = StackDepotPut(*args->stack);
- thread = args->thread;
+ thread = static_cast<AsanThread *>(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<tid_t> *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<uptr> *ptrs) {
__hwasan::hwasanThreadArgRetval().GetAllPtrsLocked(ptrs);
}
-void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {}
+void GetRunningThreadsLocked(InternalMmapVector<tid_t> *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<Range> *ranges);
void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs);
void GetRunningThreadsLocked(InternalMmapVector<tid_t> *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<tid_t> *threads) {
threads);
}
+void PrintThreads() {
+ // TODO: implement.
+}
+
void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *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<CreateThreadContextArgs *>(arg);
- if (args->stack)
- stack_id = StackDepotPut(*args->stack);
- thread = args->thread;
+ thread = static_cast<MemprofThread *>(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<const ThreadContextBase *> stacks;
+
+ registry.RunCallbackForEachThreadLocked(
+ [](ThreadContextBase *context, void *arg) {
+ static_cast<decltype(&stacks)>(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<u32> 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 <vitalybuka at google.com>
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 <assert.h>
+#include <sanitizer/lsan_interface.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <sanitizer/lsan_interface.h>
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 <vitalybuka at google.com>
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 <assert.h>
#include <sanitizer/lsan_interface.h>
>From e4752d63c55af5947e0669961f34cc6da6ffa8e7 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
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<tid_t> *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<uptr> *ptrs) {
__hwasan::hwasanThreadArgRetval().GetAllPtrsLocked(ptrs);
}
-void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {
- // TODO: implement.
-}
-void PrintThreads() {
- // TODO: implement.
-}
+void GetRunningThreadsLocked(InternalMmapVector<tid_t> *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<Range> *ranges);
void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs);
void GetRunningThreadsLocked(InternalMmapVector<tid_t> *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<tid_t> *threads) {
threads);
}
-void PrintThreads() {
- // TODO: implement.
-}
-
void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *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<const ThreadContextBase *> stacks;
-
- registry.RunCallbackForEachThreadLocked(
- [](ThreadContextBase *context, void *arg) {
- static_cast<decltype(&stacks)>(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 <iostream>
#include <vector>
-#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<TestThreadContext>,
- 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",
- "<empty stack>",
- "",
- "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
More information about the llvm-commits
mailing list