Index: lib/tsan/rtl/tsan_report.cc =================================================================== --- lib/tsan/rtl/tsan_report.cc +++ lib/tsan/rtl/tsan_report.cc @@ -380,8 +380,14 @@ Printf(" And %d more similar thread leaks.\n\n", rep->count - 1); if (ReportStack *stack = ChooseSummaryStack(rep)) { - if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames)) - ReportErrorSummary(rep_typ_str, frame->info); + if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames)) { + if (rep->typ == ReportTypeExternalRace) { + // For external races, the responsible frame is 2nd from the top + frame = frame->next; + } + if (frame) + ReportErrorSummary(rep_typ_str, frame->info); + } } if (common_flags()->print_module_map == 2) PrintModuleMap(); Index: test/tsan/Darwin/external.cc =================================================================== --- test/tsan/Darwin/external.cc +++ test/tsan/Darwin/external.cc @@ -94,13 +94,25 @@ #else // defined(SHARED_LIB) +void UserCodeRead(MyObjectRef ref) { + ObjectRead(ref); +} + +void UserCodeWrite(MyObjectRef ref, long val) { + ObjectWrite(ref, val); +} + +void UserCodeWriteAnother(MyObjectRef ref, long val) { + ObjectWriteAnother(ref, val); +} + int main(int argc, char *argv[]) { InitializeLibrary(); { MyObjectRef ref = ObjectCreate(); - std::thread t1([ref]{ ObjectRead(ref); }); - std::thread t2([ref]{ ObjectRead(ref); }); + std::thread t1([ref]{ UserCodeRead(ref); }); + std::thread t2([ref]{ UserCodeRead(ref); }); t1.join(); t2.join(); } @@ -112,8 +124,8 @@ { MyObjectRef ref = ObjectCreate(); - std::thread t1([ref]{ ObjectRead(ref); }); - std::thread t2([ref]{ ObjectWrite(ref, 66); }); + std::thread t1([ref]{ UserCodeRead(ref); }); + std::thread t2([ref]{ UserCodeWrite(ref, 66); }); t1.join(); t2.join(); } @@ -127,19 +139,20 @@ // TEST3: WARNING: ThreadSanitizer: race on a library object // TEST3: {{Mutating|read-only}} access of object MyLibrary::MyObject at - // TEST3: {{ObjectWrite|ObjectRead}} + // TEST3: {{UserCodeWrite|UserCodeRead}} // TEST3: Previous {{mutating|read-only}} access of object MyLibrary::MyObject at - // TEST3: {{ObjectWrite|ObjectRead}} + // TEST3: {{UserCodeWrite|UserCodeRead}} // TEST3: Location is MyLibrary::MyObject object of size 16 at // TEST3: {{ObjectCreate}} + // TEST3: SUMMARY: ThreadSanitizer: race on a library object {{.*}}external.cc{{.*}}{{UserCodeWrite|UserCodeRead}} fprintf(stderr, "RW test done\n"); // CHECK: RW test done { MyObjectRef ref = ObjectCreate(); - std::thread t1([ref]{ ObjectWrite(ref, 76); }); - std::thread t2([ref]{ ObjectWriteAnother(ref, 77); }); + std::thread t1([ref]{ UserCodeWrite(ref, 76); }); + std::thread t2([ref]{ UserCodeWriteAnother(ref, 77); }); t1.join(); t2.join(); } @@ -150,11 +163,12 @@ // TEST3: WARNING: ThreadSanitizer: race on a library object // TEST3: Mutating access of object MyLibrary::MyObject at - // TEST3: {{ObjectWrite|ObjectWriteAnother}} + // TEST3: {{UserCodeWrite|UserCodeWriteAnother}} // TEST3: Previous mutating access of object MyLibrary::MyObject at - // TEST3: {{ObjectWrite|ObjectWriteAnother}} + // TEST3: {{UserCodeWrite|UserCodeWriteAnother}} // TEST3: Location is MyLibrary::MyObject object of size 16 at // TEST3: {{ObjectCreate}} + // TEST3: SUMMARY: ThreadSanitizer: race on a library object {{.*}}external.cc{{.*}}{{UserCodeWrite|UserCodeWriteAnother}} fprintf(stderr, "WW test done\n"); // CHECK: WW test done