[TSan] Add a runtime flag to print full thread creation stacks up to the main thread

Currently, we only print how threads involved in data race are created from their parent threads.
Add a runtime flag 'print_full_thread_history' to print thread creation stacks for the threads involved in the data race and their ancestors up to the main thread.

Reviewed By: dvyukov

Differential Revision: https://reviews.llvm.org/D122131
This commit is contained in:
Dmitry Vyukov 2022-03-24 17:07:32 +01:00
parent f82ec5532b
commit 1d4d2cceda
3 changed files with 55 additions and 0 deletions

View file

@ -81,3 +81,6 @@ TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_MAC ? true : false,
"modules.")
TSAN_FLAG(bool, shared_ptr_interceptor, true,
"Track atomic reference counting in libc++ shared_ptr and weak_ptr.")
TSAN_FLAG(bool, print_full_thread_history, false,
"If set, prints thread creation stacks for the threads involved in "
"the report and their ancestors up to the main thread.")

View file

@ -823,6 +823,18 @@ void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
rep.AddLocation(addr_min, addr_max - addr_min);
if (flags()->print_full_thread_history) {
const ReportDesc *rep_desc = rep.GetReport();
for (uptr i = 0; i < rep_desc->threads.Size(); i++) {
Tid parent_tid = rep_desc->threads[i]->parent_tid;
if (parent_tid == kMainTid || parent_tid == kInvalidTid)
continue;
ThreadContext *parent_tctx = static_cast<ThreadContext *>(
ctx->thread_registry.GetThreadLocked(parent_tid));
rep.AddThread(parent_tctx);
}
}
#if !SANITIZER_GO
if (!((typ0 | typ1) & kAccessFree) &&
s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))

View file

@ -0,0 +1,40 @@
// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=print_full_thread_history=true %deflake %run %t 2>&1 | FileCheck %s
#include "test.h"
int Global;
void *Thread2(void *x) {
barrier_wait(&barrier);
Global++;
return NULL;
}
void *Thread3(void *x) {
Global--;
barrier_wait(&barrier);
return NULL;
}
void *Thread1(void *x) {
pthread_t t[2];
pthread_create(&t[0], NULL, Thread2, NULL);
pthread_create(&t[1], NULL, Thread3, NULL);
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
return NULL;
}
int main() {
barrier_init(&barrier, 2);
pthread_t t;
pthread_create(&t, NULL, Thread1, NULL);
pthread_join(t, NULL);
return 0;
}
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK: Thread T2 {{.*}} created by thread T1 at
// CHECK: Thread T3 {{.*}} created by thread T1 at:
// CHECK: Thread T1 {{.*}} created by main thread at:
// CHECK: SUMMARY: ThreadSanitizer: data race{{.*}}