Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NFC][sanitizer] Add Debug utility to print thread history #111948

Conversation

vitalybuka
Copy link
Collaborator

@vitalybuka vitalybuka commented Oct 11, 2024

For #111949

@llvmbot
Copy link
Member

llvmbot commented Oct 11, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Vitaly Buka (vitalybuka)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/111948.diff

3 Files Affected:

  • (modified) compiler-rt/lib/sanitizer_common/CMakeLists.txt (+1)
  • (added) compiler-rt/lib/sanitizer_common/sanitizer_thread_history.cpp (+73)
  • (added) compiler-rt/lib/sanitizer_common/sanitizer_thread_history.h (+24)
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..32a6ab1b39d3f7
--- /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 &registry, InternalScopedString &out) {
+  ThreadRegistryLock l(&registry);
+  // Stack traces are largest part of printout and they offten 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;
+  };
+
+  u32 stack_id = 0;
+  for (const ThreadContextBase *context : stacks) {
+    if (stack_id != context->stack_id) {
+      StackDepotGet(stack_id).PrintTo(&out);
+      stack_id = context->stack_id;
+    }
+    out.Append("Thread ");
+    describe_thread(context);
+    out.Append(" was created by ");
+    describe_thread(get_parent(context));
+    out.Append("\n");
+  }
+  if (!stacks.empty())
+    StackDepotGet(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

Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
@vitalybuka vitalybuka requested a review from fmayer October 11, 2024 04:49
@Enna1
Copy link
Contributor

Enna1 commented Oct 11, 2024

Will uses of __asan::DescribeThread be replaced with __sanitizer::PrintThreadHistory introduced in this patch?

@vitalybuka vitalybuka requested a review from fmayer October 11, 2024 18:40
Created using spr 1.3.4
@vitalybuka
Copy link
Collaborator Author

vitalybuka commented Oct 11, 2024

Will uses of __asan::DescribeThread be replaced with __sanitizer::PrintThreadHistory introduced in this patch?

I don't have plans to do so any time soon.

Long term I am not sure. WDYT?

DescribeThread prints, 1-thread + 1-stack and OK for existing application
PrintThreadHistory deduplicate stacks.

vitalybuka added a commit that referenced this pull request Oct 11, 2024
`parent_id` and `stack_id` represent location
where the thread was created, so it's reasonable
to keep them togeter.

For now, only Asan and MemProf use `stack_id`,
but it will be halpfull to print thread origin from
other sanitizers as well.

For #111948
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
@vitalybuka vitalybuka changed the base branch from users/vitalybuka/spr/main.nfcsanitizer-add-debug-utility-to-print-thread-history to main October 11, 2024 23:57
@vitalybuka vitalybuka merged commit aa44f59 into main Oct 11, 2024
9 of 10 checks passed
@vitalybuka vitalybuka deleted the users/vitalybuka/spr/nfcsanitizer-add-debug-utility-to-print-thread-history branch October 11, 2024 23:58
@Enna1
Copy link
Contributor

Enna1 commented Oct 13, 2024

Will uses of __asan::DescribeThread be replaced with __sanitizer::PrintThreadHistory introduced in this patch?

I don't have plans to do so any time soon.

Long term I am not sure. WDYT?

DescribeThread prints, 1-thread + 1-stack and OK for existing application PrintThreadHistory deduplicate stacks.

Currently, only Asan and MemProf "share" the same implementation of DescribeThread, and there is no use of DescribeThread in MemProf, not sure if it's worth extracting DescribeThread into sanitizer_thread_history.cpp.

@mgorny
Copy link
Member

mgorny commented Oct 15, 2024

FYI, this commit seems to have introduced test failures for me, but they seem to be incidental; I've filed #112399 about it.

DanielCChen pushed a commit to DanielCChen/llvm-project that referenced this pull request Oct 16, 2024
…111917)

`parent_id` and `stack_id` represent location
where the thread was created, so it's reasonable
to keep them togeter.

For now, only Asan and MemProf use `stack_id`,
but it will be halpfull to print thread origin from
other sanitizers as well.

For llvm#111948
DanielCChen pushed a commit to DanielCChen/llvm-project that referenced this pull request Oct 16, 2024
bricknerb pushed a commit to bricknerb/llvm-project that referenced this pull request Oct 17, 2024
…111917)

`parent_id` and `stack_id` represent location
where the thread was created, so it's reasonable
to keep them togeter.

For now, only Asan and MemProf use `stack_id`,
but it will be halpfull to print thread origin from
other sanitizers as well.

For llvm#111948
bricknerb pushed a commit to bricknerb/llvm-project that referenced this pull request Oct 17, 2024
EricWF pushed a commit to efcs/llvm-project that referenced this pull request Oct 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants