parent
7fce3ab0f2
commit
4fb340d972
|
@ -196,7 +196,7 @@ void ReportErrorSummary(const char *error_type, const char *file,
|
|||
int line, const char *function) {
|
||||
const int kMaxSize = 1024; // We don't want a summary too long.
|
||||
InternalScopedBuffer<char> buff(kMaxSize);
|
||||
internal_snprintf(buff.data(), kMaxSize, "%s %s %s:%d %s",
|
||||
internal_snprintf(buff.data(), kMaxSize, "%s: %s %s:%d %s",
|
||||
SanitizerToolName, error_type,
|
||||
file, line, function);
|
||||
__sanitizer_report_error_summary(buff.data());
|
||||
|
|
|
@ -41,3 +41,4 @@ int main() {
|
|||
// CHECK: Previous write of size 8 at {{.*}} by thread T1{{.*}}:
|
||||
// CHECK: #0 free
|
||||
// CHECK: #{{(1|2)}} Thread1
|
||||
// CHECK: SUMMARY: ThreadSanitizer: heap-use-after-free{{.*}}Thread2
|
||||
|
|
|
@ -19,3 +19,4 @@ int main() {
|
|||
// CHECK: Mutex {{.*}} created at:
|
||||
// CHECK: #0 pthread_mutex_init
|
||||
// CHECK: #1 main
|
||||
// CHECK: SUMMARY: ThreadSanitizer: destroy of a locked mutex{{.*}}main
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
pthread_t mainth;
|
||||
volatile int done;
|
||||
|
||||
static void handler(int, siginfo_t *s, void *c) {
|
||||
static void MyHandler(int, siginfo_t *s, void *c) {
|
||||
errno = 1;
|
||||
done = 1;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ static void* sendsignal(void *p) {
|
|||
int main() {
|
||||
mainth = pthread_self();
|
||||
struct sigaction act = {};
|
||||
act.sa_sigaction = &handler;
|
||||
act.sa_sigaction = &MyHandler;
|
||||
sigaction(SIGPROF, &act, 0);
|
||||
pthread_t th;
|
||||
pthread_create(&th, 0, sendsignal, 0);
|
||||
|
@ -38,5 +38,6 @@ int main() {
|
|||
}
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: signal handler spoils errno
|
||||
// CHECK: #0 handler(int, siginfo{{(_t)?}}*, void*) {{.*}}signal_errno.cc
|
||||
// CHECK: #0 MyHandler(int, siginfo{{(_t)?}}*, void*) {{.*}}signal_errno.cc
|
||||
// CHECK: SUMMARY: ThreadSanitizer: signal handler spoils errno{{.*}}MyHandler
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
static void handler(int, siginfo_t*, void*) {
|
||||
// CHECK: WARNING: ThreadSanitizer: signal-unsafe call inside of a signal
|
||||
// CHECK: #0 malloc
|
||||
// CHECK: #{{(1|2)}} handler(int, siginfo{{(_t)?}}*, void*) {{.*}}signal_malloc.cc:[[@LINE+1]]
|
||||
// CHECK: #{{(1|2)}} handler(int, siginfo{{(_t)?}}*, void*) {{.*}}signal_malloc.cc:[[@LINE+2]]
|
||||
// CHECK: SUMMARY: ThreadSanitizer: signal-unsafe call inside of a signal{{.*}}handler
|
||||
volatile char *p = (char*)malloc(1);
|
||||
p[0] = 0;
|
||||
free((void*)p);
|
||||
|
|
|
@ -23,3 +23,4 @@ int main() {
|
|||
}
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: data race
|
||||
// CHECK: SUMMARY: ThreadSanitizer: data race{{.*}}Thread
|
||||
|
|
|
@ -12,3 +12,4 @@ int main() {
|
|||
}
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: thread leak
|
||||
// CHECK: SUMMARY: ThreadSanitizer: thread leak{{.*}}main
|
||||
|
|
|
@ -43,23 +43,20 @@ 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 == 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) {
|
||||
|
@ -158,9 +155,28 @@ 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;
|
||||
}
|
||||
|
||||
static ReportStack *SkipTsanInternalFrame(ReportStack *ent) {
|
||||
if (FrameIsInternal(ent) && ent->next)
|
||||
return 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, GetPid());
|
||||
|
||||
for (uptr i = 0; i < rep->stacks.Size(); i++) {
|
||||
if (i)
|
||||
|
@ -183,6 +199,9 @@ void PrintReport(const ReportDesc *rep) {
|
|||
for (uptr i = 0; i < rep->threads.Size(); i++)
|
||||
PrintThread(rep->threads[i]);
|
||||
|
||||
if (ReportStack *ent = SkipTsanInternalFrame(ChooseSummaryStack(rep)))
|
||||
ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func);
|
||||
|
||||
Printf("==================\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -559,6 +559,7 @@ bool IsFiredSuppression(Context *ctx,
|
|||
const ScopedReport &srep,
|
||||
const StackTrace &trace);
|
||||
bool IsExpectedReport(uptr addr, uptr size);
|
||||
bool FrameIsInternal(const ReportStack *frame);
|
||||
|
||||
#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
|
||||
# define DPrintf Printf
|
||||
|
|
|
@ -496,6 +496,12 @@ bool IsFiredSuppression(Context *ctx,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FrameIsInternal(const ReportStack *frame) {
|
||||
return frame != 0 && frame->file != 0
|
||||
&& (internal_strstr(frame->file, "tsan_interceptors.cc") ||
|
||||
internal_strstr(frame->file, "sanitizer_common_interceptors.inc"));
|
||||
}
|
||||
|
||||
// On programs that use Java we see weird reports like:
|
||||
// WARNING: ThreadSanitizer: data race (pid=22512)
|
||||
// Read of size 8 at 0x7d2b00084318 by thread 100:
|
||||
|
@ -513,9 +519,7 @@ static bool IsJavaNonsense(const ReportDesc *rep) {
|
|||
&& frame->module == 0)) {
|
||||
return true;
|
||||
}
|
||||
if (frame != 0 && frame->file != 0
|
||||
&& (internal_strstr(frame->file, "tsan_interceptors.cc") ||
|
||||
internal_strstr(frame->file, "sanitizer_common_interceptors.inc"))) {
|
||||
if (FrameIsInternal(frame)) {
|
||||
frame = frame->next;
|
||||
if (frame == 0
|
||||
|| (frame->func == 0 && frame->file == 0 && frame->line == 0
|
||||
|
|
Loading…
Reference in New Issue