summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_report.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/rtl/tsan_report.cc')
-rw-r--r--lib/tsan/rtl/tsan_report.cc74
1 files changed, 53 insertions, 21 deletions
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 056dc97387b90..c95c5c86be69c 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -22,7 +22,8 @@ ReportDesc::ReportDesc()
, locs(MBlockReportLoc)
, mutexes(MBlockReportMutex)
, threads(MBlockReportThread)
- , sleep() {
+ , sleep()
+ , count() {
}
ReportMop::ReportMop()
@@ -43,23 +44,22 @@ const char *thread_name(char *buf, int tid) {
return buf;
}
-static void PrintHeader(ReportType typ) {
- Printf("WARNING: ThreadSanitizer: ");
-
+static const char *ReportTypeString(ReportType typ) {
if (typ == ReportTypeRace)
- Printf("data race");
- else if (typ == ReportTypeUseAfterFree)
- Printf("heap-use-after-free");
- else if (typ == ReportTypeThreadLeak)
- Printf("thread leak");
- else if (typ == ReportTypeMutexDestroyLocked)
- Printf("destroy of a locked mutex");
- else if (typ == ReportTypeSignalUnsafe)
- Printf("signal-unsafe call inside of a signal");
- else if (typ == ReportTypeErrnoInSignal)
- Printf("signal handler spoils errno");
-
- Printf(" (pid=%d)\n", GetPid());
+ return "data race";
+ if (typ == ReportTypeVptrRace)
+ return "data race on vptr (ctor/dtor vs virtual call)";
+ if (typ == ReportTypeUseAfterFree)
+ return "heap-use-after-free";
+ if (typ == ReportTypeThreadLeak)
+ return "thread leak";
+ if (typ == ReportTypeMutexDestroyLocked)
+ return "destroy of a locked mutex";
+ if (typ == ReportTypeSignalUnsafe)
+ return "signal-unsafe call inside of a signal";
+ if (typ == ReportTypeErrnoInSignal)
+ return "signal handler spoils errno";
+ return "";
}
void PrintStack(const ReportStack *ent) {
@@ -89,11 +89,17 @@ static void PrintMutexSet(Vector<ReportMopMutex> const& mset) {
}
}
+static const char *MopDesc(bool first, bool write, bool atomic) {
+ return atomic ? (first ? (write ? "Atomic write" : "Atomic read")
+ : (write ? "Previous atomic write" : "Previous atomic read"))
+ : (first ? (write ? "Write" : "Read")
+ : (write ? "Previous write" : "Previous read"));
+}
+
static void PrintMop(const ReportMop *mop, bool first) {
char thrbuf[kThreadBufSize];
Printf(" %s of size %d at %p by %s",
- (first ? (mop->write ? "Write" : "Read")
- : (mop->write ? "Previous write" : "Previous read")),
+ MopDesc(first, mop->write, mop->atomic),
mop->size, (void*)mop->addr,
thread_name(thrbuf, mop->tid));
PrintMutexSet(mop->mset);
@@ -135,7 +141,7 @@ static void PrintThread(const ReportThread *rt) {
if (rt->id == 0) // Little sense in describing the main thread.
return;
Printf(" Thread T%d", rt->id);
- if (rt->name)
+ if (rt->name && rt->name[0] != '\0')
Printf(" '%s'", rt->name);
char thrbuf[kThreadBufSize];
Printf(" (tid=%zu, %s) created by %s",
@@ -152,9 +158,29 @@ static void PrintSleep(const ReportStack *s) {
PrintStack(s);
}
+static ReportStack *ChooseSummaryStack(const ReportDesc *rep) {
+ if (rep->mops.Size())
+ return rep->mops[0]->stack;
+ if (rep->stacks.Size())
+ return rep->stacks[0];
+ if (rep->mutexes.Size())
+ return rep->mutexes[0]->stack;
+ if (rep->threads.Size())
+ return rep->threads[0]->stack;
+ return 0;
+}
+
+ReportStack *SkipTsanInternalFrames(ReportStack *ent) {
+ while (FrameIsInternal(ent) && ent->next)
+ ent = ent->next;
+ return ent;
+}
+
void PrintReport(const ReportDesc *rep) {
Printf("==================\n");
- PrintHeader(rep->typ);
+ const char *rep_typ_str = ReportTypeString(rep->typ);
+ Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str,
+ (int)internal_getpid());
for (uptr i = 0; i < rep->stacks.Size(); i++) {
if (i)
@@ -177,6 +203,12 @@ void PrintReport(const ReportDesc *rep) {
for (uptr i = 0; i < rep->threads.Size(); i++)
PrintThread(rep->threads[i]);
+ if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
+ Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
+
+ if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep)))
+ ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func);
+
Printf("==================\n");
}