[compiler-rt] r274548 - [tsan] dispatch_once interceptor will cause a crash/deadlock when the original dispatch_once is used

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 5 06:39:54 PDT 2016


Author: kuba.brecka
Date: Tue Jul  5 08:39:54 2016
New Revision: 274548

URL: http://llvm.org/viewvc/llvm-project?rev=274548&view=rev
Log:
[tsan] dispatch_once interceptor will cause a crash/deadlock when the original dispatch_once is used

Because we use SCOPED_TSAN_INTERCEPTOR in the dispatch_once interceptor, the original dispatch_once can also be sometimes called (when ignores are enabled or when thr->is_inited is false). However the original dispatch_once function doesn’t expect to find “2” in the storage and it will spin forever (but we use “2” to indicate that the initialization is already done, so no waiting is necessary). This patch makes sure we never call the original dispatch_once.

Differential Revision: http://reviews.llvm.org/D21976


Added:
    compiler-rt/trunk/test/tsan/Darwin/dispatch_once_deadlock.mm
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc?rev=274548&r1=274547&r2=274548&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc Tue Jul  5 08:39:54 2016
@@ -219,7 +219,7 @@ TSAN_INTERCEPTOR(void, dispatch_after_f,
 #undef dispatch_once
 TSAN_INTERCEPTOR(void, dispatch_once, dispatch_once_t *predicate,
                  dispatch_block_t block) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_once, predicate, block);
+  SCOPED_INTERCEPTOR_RAW(dispatch_once, predicate, block);
   atomic_uint32_t *a = reinterpret_cast<atomic_uint32_t *>(predicate);
   u32 v = atomic_load(a, memory_order_acquire);
   if (v == 0 &&
@@ -241,7 +241,7 @@ TSAN_INTERCEPTOR(void, dispatch_once, di
 #undef dispatch_once_f
 TSAN_INTERCEPTOR(void, dispatch_once_f, dispatch_once_t *predicate,
                  void *context, dispatch_function_t function) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_once_f, predicate, context, function);
+  SCOPED_INTERCEPTOR_RAW(dispatch_once_f, predicate, context, function);
   SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
   WRAP(dispatch_once)(predicate, ^(void) {
     function(context);

Added: compiler-rt/trunk/test/tsan/Darwin/dispatch_once_deadlock.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/dispatch_once_deadlock.mm?rev=274548&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/dispatch_once_deadlock.mm (added)
+++ compiler-rt/trunk/test/tsan/Darwin/dispatch_once_deadlock.mm Tue Jul  5 08:39:54 2016
@@ -0,0 +1,41 @@
+// Check that calling dispatch_once from a report callback works.
+
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 not %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+#import <pthread.h>
+
+long g = 0;
+long h = 0;
+void f() {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    g++;
+  });
+  h++;
+}
+
+extern "C" void __tsan_on_report() {
+  fprintf(stderr, "Report.\n");
+  f();
+}
+
+int main() {
+  fprintf(stderr, "Hello world.\n");
+
+  f();
+
+  pthread_mutex_t mutex = {0};
+  pthread_mutex_lock(&mutex);
+
+  fprintf(stderr, "g = %ld.\n", g);
+  fprintf(stderr, "h = %ld.\n", h);
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: Report.
+// CHECK: g = 1
+// CHECK: h = 2
+// CHECK: Done.




More information about the llvm-commits mailing list