summaryrefslogtreecommitdiff
path: root/lib/lsan
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2018-05-09 23:02:14 +0000
committerVitaly Buka <vitalybuka@google.com>2018-05-09 23:02:14 +0000
commit64a45fee88b66222e6a7618cfb6de62f9ed3125b (patch)
tree4cc15bc2d4db34f0751b36c87ed814156852336e /lib/lsan
parent88cf0dea781fa6840a3255e4edc15b32e91a8cb6 (diff)
[lsan] Report unsuspended threads
Summary: Leak checker needs to suspend all process threads. If we have some running thread in registry but not suspended we can have false leak report. So we will report this case here for future debugging. Reviewers: eugenis Subscribers: kubamracek, llvm-commits Differential Revision: https://reviews.llvm.org/D46663 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@331936 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/lsan')
-rw-r--r--lib/lsan/lsan_common.cc30
-rw-r--r--lib/lsan/lsan_common.h2
-rw-r--r--lib/lsan/lsan_thread.cc5
3 files changed, 35 insertions, 2 deletions
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index bdc825d76..eaa5cadc8 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -15,14 +15,15 @@
#include "lsan_common.h"
#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_suppressions.h"
-#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
#include "sanitizer_common/sanitizer_tls_get_addr.h"
#if CAN_SANITIZE_LEAKS
@@ -526,11 +527,36 @@ struct CheckForLeaksParam {
LeakReport leak_report;
};
+static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
+ const InternalMmapVector<tid_t> &suspended_threads =
+ *(const InternalMmapVector<tid_t> *)arg;
+ if (tctx->status == ThreadStatusRunning) {
+ uptr i = InternalLowerBound(suspended_threads, 0, suspended_threads.size(),
+ tctx->os_id, CompareLess<int>());
+ if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
+ Report("Running thread %d was not suspended. False leaks are possible.\n",
+ tctx->os_id);
+ };
+}
+
+static void ReportUnsuspendedThreads(
+ const SuspendedThreadsList &suspended_threads) {
+ InternalMmapVector<tid_t> threads(suspended_threads.ThreadCount());
+ for (uptr i = 0; i < suspended_threads.ThreadCount(); ++i)
+ threads[i] = suspended_threads.GetThreadID(i);
+
+ Sort(threads.data(), threads.size());
+
+ GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+ &ReportIfNotSuspended, &threads);
+}
+
static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads,
void *arg) {
CheckForLeaksParam *param = reinterpret_cast<CheckForLeaksParam *>(arg);
CHECK(param);
CHECK(!param->success);
+ ReportUnsuspendedThreads(suspended_threads);
ClassifyAllChunks(suspended_threads);
ForEachChunk(CollectLeaksCb, &param->leak_report);
// Clean up for subsequent leak checks. This assumes we did not overwrite any
diff --git a/lib/lsan/lsan_common.h b/lib/lsan/lsan_common.h
index 2bffed4a5..1d1e1e462 100644
--- a/lib/lsan/lsan_common.h
+++ b/lib/lsan/lsan_common.h
@@ -47,6 +47,7 @@
namespace __sanitizer {
class FlagParser;
+class ThreadRegistry;
struct DTLS;
}
@@ -204,6 +205,7 @@ bool WordIsPoisoned(uptr addr);
// Wrappers for ThreadRegistry access.
void LockThreadRegistry();
void UnlockThreadRegistry();
+ThreadRegistry *GetThreadRegistryLocked();
bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
uptr *cache_end, DTLS **dtls);
diff --git a/lib/lsan/lsan_thread.cc b/lib/lsan/lsan_thread.cc
index 4404c8cc5..a25aff379 100644
--- a/lib/lsan/lsan_thread.cc
+++ b/lib/lsan/lsan_thread.cc
@@ -155,4 +155,9 @@ void UnlockThreadRegistry() {
thread_registry->Unlock();
}
+ThreadRegistry *GetThreadRegistryLocked() {
+ thread_registry->CheckLocked();
+ return thread_registry;
+}
+
} // namespace __lsan