[lsan] Move symbolization and reporting out of StopTheWorld callback.
llvm-svn: 184303
This commit is contained in:
parent
f86ae72e6d
commit
dac35c24c0
|
|
@ -13,6 +13,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 33554432 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ void ConfirmPointerHasSurvived() {
|
|||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK-sanity: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
// CHECK-sanity: Value after LSan: [[ADDR]].
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -46,6 +46,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,6 @@ int main() {
|
|||
exit(0);
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -31,6 +31,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ int main(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -32,6 +32,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,6 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
// CHECK: Test alloc: [[ADDR:.*]].
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: Directly leaked 1337 byte object at [[ADDR]]
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: SUMMARY: LeakSanitizer:
|
||||
|
|
|
|||
|
|
@ -275,45 +275,34 @@ void PrintLeakedCb::operator()(void *p) const {
|
|||
LsanMetadata m(p);
|
||||
if (!m.allocated()) return;
|
||||
if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
|
||||
Printf("%s leaked %llu byte object at %p\n",
|
||||
Printf("%s leaked %llu byte object at %p.\n",
|
||||
m.tag() == kDirectlyLeaked ? "Directly" : "Indirectly",
|
||||
m.requested_size(), p);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintLeaked() {
|
||||
Printf("Reporting individual objects:\n");
|
||||
Printf("============================\n");
|
||||
ForEachChunk(PrintLeakedCb());
|
||||
Printf("\n");
|
||||
Printf("Reporting individual objects:\n");
|
||||
ForEachChunk(PrintLeakedCb());
|
||||
}
|
||||
|
||||
enum LeakCheckResult {
|
||||
kFatalError,
|
||||
kLeaksFound,
|
||||
kNoLeaks
|
||||
struct DoLeakCheckParam {
|
||||
bool success;
|
||||
LeakReport leak_report;
|
||||
};
|
||||
|
||||
static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads,
|
||||
void *arg) {
|
||||
LeakCheckResult *result = reinterpret_cast<LeakCheckResult *>(arg);
|
||||
CHECK_EQ(*result, kFatalError);
|
||||
DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg);
|
||||
CHECK(param);
|
||||
CHECK(!param->success);
|
||||
CHECK(param->leak_report.IsEmpty());
|
||||
ClassifyAllChunks(suspended_threads);
|
||||
LeakReport leak_report;
|
||||
CollectLeaks(&leak_report);
|
||||
if (leak_report.IsEmpty()) {
|
||||
*result = kNoLeaks;
|
||||
return;
|
||||
}
|
||||
Printf("\n");
|
||||
Printf("=================================================================\n");
|
||||
Report("ERROR: LeakSanitizer: detected memory leaks\n");
|
||||
leak_report.PrintLargest(flags()->max_leaks);
|
||||
if (flags()->report_objects)
|
||||
CollectLeaks(¶m->leak_report);
|
||||
if (!param->leak_report.IsEmpty() && flags()->report_objects)
|
||||
PrintLeaked();
|
||||
leak_report.PrintSummary();
|
||||
Printf("\n");
|
||||
*result = kLeaksFound;
|
||||
param->success = true;
|
||||
}
|
||||
|
||||
void DoLeakCheck() {
|
||||
|
|
@ -321,16 +310,25 @@ void DoLeakCheck() {
|
|||
static bool already_done;
|
||||
CHECK(!already_done);
|
||||
already_done = true;
|
||||
LeakCheckResult result = kFatalError;
|
||||
|
||||
DoLeakCheckParam param;
|
||||
param.success = false;
|
||||
LockThreadRegistry();
|
||||
LockAllocator();
|
||||
StopTheWorld(DoLeakCheckCallback, &result);
|
||||
StopTheWorld(DoLeakCheckCallback, ¶m);
|
||||
UnlockAllocator();
|
||||
UnlockThreadRegistry();
|
||||
if (result == kFatalError) {
|
||||
|
||||
if (!param.success) {
|
||||
Report("LeakSanitizer has encountered a fatal error.\n");
|
||||
Die();
|
||||
} else if (result == kLeaksFound) {
|
||||
}
|
||||
if (!param.leak_report.IsEmpty()) {
|
||||
Printf("\n================================================================="
|
||||
"\n");
|
||||
Report("ERROR: LeakSanitizer: detected memory leaks\n");
|
||||
param.leak_report.PrintLargest(flags()->max_leaks);
|
||||
param.leak_report.PrintSummary();
|
||||
if (flags()->exitcode)
|
||||
internal__exit(flags()->exitcode);
|
||||
}
|
||||
|
|
@ -396,7 +394,7 @@ void LeakReport::PrintSummary() {
|
|||
bytes += leaks_[i].total_size;
|
||||
allocations += leaks_[i].hit_count;
|
||||
}
|
||||
Printf("SUMMARY: LeakSanitizer: %llu byte(s) leaked in %llu allocation(s).\n",
|
||||
Printf("SUMMARY: LeakSanitizer: %llu byte(s) leaked in %llu allocation(s).\n\n",
|
||||
bytes, allocations);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -278,11 +278,20 @@ class ScopedStackSpaceWithGuard {
|
|||
uptr guard_start_;
|
||||
};
|
||||
|
||||
static void WipeStack() {
|
||||
char arr[256];
|
||||
internal_memset(arr, 0, sizeof(arr));
|
||||
}
|
||||
|
||||
static sigset_t blocked_sigset;
|
||||
static sigset_t old_sigset;
|
||||
static struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)];
|
||||
|
||||
void StopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
// Glibc's sigaction() has a side-effect where it copies garbage stack values
|
||||
// into oldact, which can cause false negatives in LSan. As a quick workaround
|
||||
// we zero some stack space here.
|
||||
WipeStack();
|
||||
// Block all signals that can be blocked safely, and install default handlers
|
||||
// for the remaining signals.
|
||||
// We cannot allow user-defined handlers to run while the ThreadSuspender
|
||||
|
|
|
|||
Loading…
Reference in New Issue