From 0bf5ec2812ebde491d9baee26b2f58403e20bca2 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Thu, 30 Mar 2017 15:48:25 +0000 Subject: [PATCH] [tsan] Add interceptor for xpc_connection_cancel to avoid false positives TSan reports a false positive when using xpc_connection_cancel. We're missing a happens-before edge from xpc_connection_cancel to the event handler on the same connection. Differential Revision: https://reviews.llvm.org/D31475 llvm-svn: 299086 --- compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc | 6 ++++ compiler-rt/test/tsan/Darwin/xpc-cancel.mm | 37 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 compiler-rt/test/tsan/Darwin/xpc-cancel.mm diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc index fc5eb04..f6bf8a0 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -281,6 +281,12 @@ TSAN_INTERCEPTOR(void, xpc_connection_send_message_with_reply, (connection, message, replyq, new_handler); } +TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) { + SCOPED_TSAN_INTERCEPTOR(xpc_connection_cancel, connection); + Release(thr, pc, (uptr)connection); + REAL(xpc_connection_cancel)(connection); +} + // On macOS, libc++ is always linked dynamically, so intercepting works the // usual way. #define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR diff --git a/compiler-rt/test/tsan/Darwin/xpc-cancel.mm b/compiler-rt/test/tsan/Darwin/xpc-cancel.mm new file mode 100644 index 0000000..5e326b7 --- /dev/null +++ b/compiler-rt/test/tsan/Darwin/xpc-cancel.mm @@ -0,0 +1,37 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 | FileCheck %s + +#import +#import + +long global; + +int main(int argc, const char *argv[]) { + fprintf(stderr, "Hello world.\n"); + + dispatch_queue_t server_q = dispatch_queue_create("server.queue", DISPATCH_QUEUE_CONCURRENT); + xpc_connection_t server_conn = xpc_connection_create(NULL, server_q); + + xpc_connection_set_event_handler(server_conn, ^(xpc_object_t client) { + if (client == XPC_ERROR_CONNECTION_INTERRUPTED || client == XPC_ERROR_CONNECTION_INVALID) { + global = 43; + + dispatch_async(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + } + }); + xpc_connection_resume(server_conn); + + global = 42; + + xpc_connection_cancel(server_conn); + + CFRunLoopRun(); + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK: Done. -- 2.7.4