diff options
-rw-r--r-- | lib/tsan/rtl/tsan_libdispatch_mac.cc | 5 | ||||
-rw-r--r-- | test/tsan/Darwin/gcd-sync-block-copy.mm | 34 |
2 files changed, 35 insertions, 4 deletions
diff --git a/lib/tsan/rtl/tsan_libdispatch_mac.cc b/lib/tsan/rtl/tsan_libdispatch_mac.cc index d6c1ca662..23c4380fb 100644 --- a/lib/tsan/rtl/tsan_libdispatch_mac.cc +++ b/lib/tsan/rtl/tsan_libdispatch_mac.cc @@ -185,11 +185,8 @@ static void invoke_and_release_block(void *param) { TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, \ DISPATCH_NOESCAPE dispatch_block_t block) { \ SCOPED_TSAN_INTERCEPTOR(name, q, block); \ - SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \ - dispatch_block_t heap_block = Block_copy(block); \ - SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \ tsan_block_context_t new_context = { \ - q, heap_block, &invoke_and_release_block, false, true, barrier, 0}; \ + q, block, &invoke_and_release_block, false, true, barrier, 0}; \ Release(thr, pc, (uptr)&new_context); \ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \ REAL(name##_f)(q, &new_context, dispatch_callback_wrap); \ diff --git a/test/tsan/Darwin/gcd-sync-block-copy.mm b/test/tsan/Darwin/gcd-sync-block-copy.mm new file mode 100644 index 000000000..87658d7f3 --- /dev/null +++ b/test/tsan/Darwin/gcd-sync-block-copy.mm @@ -0,0 +1,34 @@ +// This test verifies that dispatch_sync() doesn't actually copy the block under TSan (without TSan, it doesn't). + +// RUN: %clang_tsan -fno-sanitize=thread %s -o %t_no_tsan -framework Foundation +// RUN: %run %t_no_tsan 2>&1 | FileCheck %s + +// RUN: %clang_tsan %s -o %t_with_tsan -framework Foundation +// RUN: %run %t_with_tsan 2>&1 | FileCheck %s + +#import <Foundation/Foundation.h> + +@interface MyClass : NSObject +@end + +@implementation MyClass +- (instancetype)retain { + // Copying the dispatch_sync'd block below will increment the retain count of + // this object. Abort if that happens. + abort(); +} +@end + +int main(int argc, const char* argv[]) { + dispatch_queue_t q = dispatch_queue_create("my.queue", NULL); + id object = [[MyClass alloc] init]; + dispatch_sync(q, ^{ + NSLog(@"%@", object); + }); + [object release]; + NSLog(@"Done."); + return 0; +} + +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer |