[compiler-rt] r235293 - tsan: fix handling of pthread_detach

Dmitry Vyukov dvyukov at google.com
Mon Apr 20 03:35:10 PDT 2015


Author: dvyukov
Date: Mon Apr 20 05:35:10 2015
New Revision: 235293

URL: http://llvm.org/viewvc/llvm-project?rev=235293&view=rev
Log:
tsan: fix handling of pthread_detach

Fixes https://llvm.org/bugs/show_bug.cgi?id=23235

If pthread_create is followed by pthread_detach,
the new thread may not acquire synchronize with
the parent thread.


Added:
    compiler-rt/trunk/test/tsan/thread_detach2.c
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=235293&r1=235292&r2=235293&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Mon Apr 20 05:35:10 2015
@@ -935,8 +935,8 @@ extern "C" void *__tsan_thread_start_fun
     ThreadIgnoreEnd(thr, 0);
     while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
       pthread_yield();
-    atomic_store(&p->tid, 0, memory_order_release);
     ThreadStart(thr, tid, GetTid());
+    atomic_store(&p->tid, 0, memory_order_release);
   }
   void *res = callback(param);
   // Prevent the callback from being tail called,
@@ -984,6 +984,13 @@ TSAN_INTERCEPTOR(int, pthread_create,
   if (res == 0) {
     int tid = ThreadCreate(thr, pc, *(uptr*)th, detached);
     CHECK_NE(tid, 0);
+    // Synchronization on p.tid serves two purposes:
+    // 1. ThreadCreate must finish before the new thread starts.
+    //    Otherwise the new thread can call pthread_detach, but the pthread_t
+    //    identifier is not yet registered in ThreadRegistry by ThreadCreate.
+    // 2. ThreadStart must finish before this thread continues.
+    //    Otherwise, this thread can call pthread_detach and reset thr->sync
+    //    before the new thread got a chance to acquire from it in ThreadStart.
     atomic_store(&p.tid, tid, memory_order_release);
     while (atomic_load(&p.tid, memory_order_acquire) != 0)
       pthread_yield();

Added: compiler-rt/trunk/test/tsan/thread_detach2.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/thread_detach2.c?rev=235293&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/thread_detach2.c (added)
+++ compiler-rt/trunk/test/tsan/thread_detach2.c Mon Apr 20 05:35:10 2015
@@ -0,0 +1,28 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "test.h"
+
+// Test for https://llvm.org/bugs/show_bug.cgi?id=23235
+// The bug was that synchronization between thread creation and thread start
+// is not established if pthread_create is followed by pthread_detach.
+
+int x;
+
+void *Thread(void *a) {
+  x = 42;
+  barrier_wait(&barrier);
+  return 0;
+}
+
+int main() {
+  barrier_init(&barrier, 2);
+  pthread_t t;
+  x = 43;
+  pthread_create(&t, 0, Thread, 0);
+  pthread_detach(t);
+  barrier_wait(&barrier);
+  printf("PASS\n");
+  return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK: PASS





More information about the llvm-commits mailing list