[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
This commit is contained in:
Kuba Mracek 2017-03-30 15:48:25 +00:00
parent fe7e91b003
commit 0bf5ec2812
2 changed files with 43 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,37 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
#import <xpc/xpc.h>
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.