Skip to content

Commit e1cff8b

Browse files
authored
[lsan] Add debug option to "deflake" leaks (#112037)
There are hard to debug leaks which look like false. In general, repeating leak checking should not affect set of leaks significantly, especial `at_exit` leak checking. But if we see significant discrepancy, it may give us a clue for investigation.
1 parent 9025202 commit e1cff8b

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

compiler-rt/lib/lsan/lsan_common.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ static bool PrintResults(LeakReport &report) {
778778
return false;
779779
}
780780

781-
static bool CheckForLeaks() {
781+
static bool CheckForLeaksOnce() {
782782
if (&__lsan_is_turned_off && __lsan_is_turned_off()) {
783783
VReport(1, "LeakSanitizer is disabled\n");
784784
return false;
@@ -830,6 +830,12 @@ static bool CheckForLeaks() {
830830
}
831831
}
832832

833+
static bool CheckForLeaks() {
834+
int leaking_tries = 0;
835+
for (int i = 0; i < flags()->tries; ++i) leaking_tries += CheckForLeaksOnce();
836+
return leaking_tries == flags()->tries;
837+
}
838+
833839
static bool has_reported_leaks = false;
834840
bool HasReportedLeaks() { return has_reported_leaks; }
835841

compiler-rt/lib/lsan/lsan_flags.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ LSAN_FLAG(bool, use_poisoned, false,
4343
"Consider pointers found in poisoned memory to be valid.")
4444
LSAN_FLAG(bool, log_pointers, false, "Debug logging")
4545
LSAN_FLAG(bool, log_threads, false, "Debug logging")
46+
LSAN_FLAG(int, tries, 1, "Debug option to repeat leak checking multiple times")
4647
LSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
4748
LSAN_FLAG(int, thread_suspend_fail, 1,
4849
"Behaviour if thread suspendion all thread (0 - "
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test retries option of lsan.
2+
// RUN: %clang_lsan %s -o %t
3+
// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0 %run %t foo 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK1
4+
// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0:tries=12 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK12
5+
6+
#include <assert.h>
7+
#include <sanitizer/lsan_interface.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <unistd.h>
11+
12+
void *p;
13+
14+
int main(int argc, char *argv[]) {
15+
fprintf(stderr, "Test alloc: %p.\n", malloc(1337));
16+
// CHECK: Test alloc:
17+
18+
assert(__lsan_do_recoverable_leak_check() == 1);
19+
// CHECK1-COUNT-1: SUMMARY: {{.*}}Sanitizer: 1337 byte
20+
// CHECK12-COUNT-12: SUMMARY: {{.*}}Sanitizer: 1337 byte
21+
22+
_exit(0);
23+
}

0 commit comments

Comments
 (0)