summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorKuba Brecka <kuba.brecka@gmail.com>2016-01-14 12:24:37 +0000
committerKuba Brecka <kuba.brecka@gmail.com>2016-01-14 12:24:37 +0000
commit0626dd0d3b6b6251448344afaf44f9a65e4d00ca (patch)
tree8286626b9bca4dea3009db1fdc72a2bdee56fc41 /compiler-rt
parentd0d85d22f877efb232cce509a044d54ae9874bbe (diff)
downloadbcm5719-llvm-0626dd0d3b6b6251448344afaf44f9a65e4d00ca.tar.gz
bcm5719-llvm-0626dd0d3b6b6251448344afaf44f9a65e4d00ca.zip
[tsan] Introduce a "ignore_interceptors_accesses" option
On OS X, TSan already passes all unit and lit tests, but for real-world applications (even very simple ones), we currently produce a lot of false positive reports about data races. This makes TSan useless at this point, because the noise dominates real bugs. This introduces a runtime flag, "ignore_interceptors_accesses", off by default, which makes TSan ignore all memory accesses that happen from interceptors. This will significantly lower the coverage and miss a lot of bugs, but it eliminates most of the current false positives on OS X. Differential Revision: http://reviews.llvm.org/D15189 llvm-svn: 257760
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc10
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.inc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc10
-rw-r--r--compiler-rt/test/tsan/Darwin/ignored-interceptors.mm56
4 files changed, 78 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 2a748cdc685..769e08cabbb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -143,6 +143,14 @@
#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
#endif
+#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
+#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
+#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
+#endif
+
struct FileMetadata {
// For open_memstream().
char **addr;
@@ -3304,7 +3312,9 @@ INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
INTERCEPTOR(void, _exit, int status) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
+ COMMON_INTERCEPTOR_USER_CALLBACK_START();
int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
+ COMMON_INTERCEPTOR_USER_CALLBACK_END();
if (status == 0) status = status1;
REAL(_exit)(status);
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.inc b/compiler-rt/lib/tsan/rtl/tsan_flags.inc
index ab9ca992493..a9f45200c42 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.inc
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.inc
@@ -76,3 +76,5 @@ TSAN_FLAG(int, io_sync, 1,
TSAN_FLAG(bool, die_after_fork, true,
"Die after multi-threaded fork if the child creates new threads.")
TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
+TSAN_FLAG(bool, ignore_interceptors_accesses, false,
+ "Ignore reads and writes from all interceptors.")
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index a6c01bf9aeb..a42a8aaa49d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -286,9 +286,11 @@ ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
thr_->in_ignored_lib = true;
ThreadIgnoreBegin(thr_, pc_);
}
+ if (flags()->ignore_interceptors_accesses) ThreadIgnoreBegin(thr_, pc_);
}
ScopedInterceptor::~ScopedInterceptor() {
+ if (flags()->ignore_interceptors_accesses) ThreadIgnoreEnd(thr_, pc_);
if (in_ignored_lib_) {
thr_->in_ignored_lib = false;
ThreadIgnoreEnd(thr_, pc_);
@@ -301,6 +303,7 @@ ScopedInterceptor::~ScopedInterceptor() {
}
void ScopedInterceptor::UserCallbackStart() {
+ if (flags()->ignore_interceptors_accesses) ThreadIgnoreEnd(thr_, pc_);
if (in_ignored_lib_) {
thr_->in_ignored_lib = false;
ThreadIgnoreEnd(thr_, pc_);
@@ -312,6 +315,7 @@ void ScopedInterceptor::UserCallbackEnd() {
thr_->in_ignored_lib = true;
ThreadIgnoreBegin(thr_, pc_);
}
+ if (flags()->ignore_interceptors_accesses) ThreadIgnoreBegin(thr_, pc_);
}
#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
@@ -2413,6 +2417,12 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
*begin = *end = 0; \
}
+#define COMMON_INTERCEPTOR_USER_CALLBACK_START() \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START()
+
+#define COMMON_INTERCEPTOR_USER_CALLBACK_END() \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END()
+
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#define TSAN_SYSCALL() \
diff --git a/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm b/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm
new file mode 100644
index 00000000000..8a4ecf1eed4
--- /dev/null
+++ b/compiler-rt/test/tsan/Darwin/ignored-interceptors.mm
@@ -0,0 +1,56 @@
+// Check that ignore_interceptors_accesses=1 supresses reporting races from
+// system libraries on OS X. There are currently false positives coming from
+// libxpc, libdispatch, CoreFoundation and others, because these libraries use
+// TSan-invisible atomics as synchronization.
+
+// RUN: %clang_tsan %s -o %t -framework Foundation
+
+// Check that without the flag, there are false positives.
+// RUN: %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RACE
+
+// With ignore_interceptors_accesses=1, no races are reported.
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK
+
+// With ignore_interceptors_accesses=1, races in user's code are still reported.
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t race 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RACE
+
+#import <Foundation/Foundation.h>
+
+#import "../test.h"
+
+long global;
+
+void *Thread1(void *x) {
+ barrier_wait(&barrier);
+ global = 42;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ global = 43;
+ barrier_wait(&barrier);
+ return NULL;
+}
+
+int main(int argc, char *argv[]) {
+ NSLog(@"Hello world.");
+
+ // NSUserDefaults uses XPC which triggers the false positive.
+ NSDictionary *d = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
+ NSLog(@"d = %@", d);
+
+ if (argc > 1 && strcmp(argv[1], "race") == 0) {
+ barrier_init(&barrier, 2);
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ }
+
+ NSLog(@"Done.");
+}
+
+// CHECK: Hello world.
+// CHECK-RACE: SUMMARY: ThreadSanitizer: data race
+// CHECK: Done.
OpenPOWER on IntegriCloud