Index: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc =================================================================== --- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc +++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -281,6 +281,12 @@ (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 Index: compiler-rt/trunk/test/tsan/Darwin/xpc-cancel.mm =================================================================== --- compiler-rt/trunk/test/tsan/Darwin/xpc-cancel.mm +++ compiler-rt/trunk/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.