[compiler-rt] r268782 - tsan: fix a crash
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Fri May 6 12:35:23 PDT 2016
Author: dvyukov
Date: Fri May 6 14:35:22 2016
New Revision: 268782
URL: http://llvm.org/viewvc/llvm-project?rev=268782&view=rev
Log:
tsan: fix a crash
Fixes crash reported in:
https://bugs.chromium.org/p/v8/issues/detail?id=4995
The problem is that we don't have a processor in a free interceptor
during thread exit.
The crash was introduced by introduction of Processors.
However, previously we silently leaked memory which wasn't any better.
Added:
compiler-rt/trunk/test/tsan/pthread_key.cc
Modified:
compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h
compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc Fri May 6 14:35:22 2016
@@ -63,10 +63,29 @@ Allocator *allocator() {
return reinterpret_cast<Allocator*>(&allocator_placeholder);
}
+struct GlobalProc {
+ Mutex mtx;
+ Processor *proc;
+
+ GlobalProc()
+ : mtx(MutexTypeGlobalProc, StatMtxGlobalProc)
+ , proc(ProcCreate()) {
+ }
+};
+
+static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64);
+GlobalProc *global_proc() {
+ return reinterpret_cast<GlobalProc*>(&global_proc_placeholder);
+}
+
void InitializeAllocator() {
allocator()->Init(common_flags()->allocator_may_return_null);
}
+void InitializeAllocatorLate() {
+ new(global_proc()) GlobalProc();
+}
+
void AllocatorProcStart(Processor *proc) {
allocator()->InitCache(&proc->alloc_cache);
internal_allocator()->InitCache(&proc->internal_alloc_cache);
@@ -118,11 +137,29 @@ void *user_calloc(ThreadState *thr, uptr
}
void user_free(ThreadState *thr, uptr pc, void *p, bool signal) {
+ GlobalProc *gp = nullptr;
+ if (thr->proc() == nullptr) {
+ // If we don't have a proc, use the global one.
+ // There is currently only one known case where this path is triggered:
+ // __interceptor_free
+ // __nptl_deallocate_tsd
+ // start_thread
+ // clone
+ // Ideally, we destroy thread state (and unwire proc) when a thread actually
+ // exits (i.e. when we join/wait it). Then we would not need the global proc
+ gp = global_proc();
+ gp->mtx.Lock();
+ ProcWire(gp->proc, thr);
+ }
if (ctx && ctx->initialized)
OnUserFree(thr, pc, (uptr)p, true);
allocator()->Deallocate(&thr->proc()->alloc_cache, p);
if (signal)
SignalUnsafeCall(thr, pc);
+ if (gp) {
+ ProcUnwire(gp->proc, thr);
+ gp->mtx.Unlock();
+ }
}
void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h Fri May 6 14:35:22 2016
@@ -20,6 +20,7 @@ namespace __tsan {
const uptr kDefaultAlignment = 16;
void InitializeAllocator();
+void InitializeAllocatorLate();
void ReplaceSystemMalloc();
void AllocatorProcStart(Processor *proc);
void AllocatorProcFinish(Processor *proc);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc Fri May 6 14:35:22 2016
@@ -43,6 +43,7 @@ static MutexType CanLockTab[MutexTypeCou
/*11 MutexTypeDDetector*/ {},
/*12 MutexTypeFired*/ {MutexTypeLeaf},
/*13 MutexTypeRacy*/ {MutexTypeLeaf},
+ /*14 MutexTypeGlobalProc*/ {},
};
static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h Fri May 6 14:35:22 2016
@@ -34,6 +34,7 @@ enum MutexType {
MutexTypeDDetector,
MutexTypeFired,
MutexTypeRacy,
+ MutexTypeGlobalProc,
// This must be the last.
MutexTypeCount
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc Fri May 6 14:35:22 2016
@@ -341,6 +341,7 @@ void Initialize(ThreadState *thr) {
InitializeDynamicAnnotations();
#ifndef SANITIZER_GO
InitializeShadowMemory();
+ InitializeAllocatorLate();
#endif
// Setup correct file descriptor for error reports.
__sanitizer_set_report_path(common_flags()->log_path);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Fri May 6 14:35:22 2016
@@ -168,6 +168,7 @@ void StatOutput(u64 *stat) {
name[StatMtxFired] = " FiredSuppressions ";
name[StatMtxRacy] = " RacyStacks ";
name[StatMtxFD] = " FD ";
+ name[StatMtxGlobalProc] = " GlobalProc ";
Printf("Statistics:\n");
for (int i = 0; i < StatCnt; i++)
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=268782&r1=268781&r2=268782&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Fri May 6 14:35:22 2016
@@ -173,6 +173,7 @@ enum StatType {
StatMtxFired,
StatMtxRacy,
StatMtxFD,
+ StatMtxGlobalProc,
// This must be the last.
StatCnt
Added: compiler-rt/trunk/test/tsan/pthread_key.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/pthread_key.cc?rev=268782&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/pthread_key.cc (added)
+++ compiler-rt/trunk/test/tsan/pthread_key.cc Fri May 6 14:35:22 2016
@@ -0,0 +1,39 @@
+// RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// Extracted from:
+// https://bugs.chromium.org/p/v8/issues/detail?id=4995
+
+#include "test.h"
+
+void* thr(void* arg) {
+ const int N = 32;
+ pthread_key_t keys_[N];
+ for (size_t i = 0; i < N; ++i) {
+ int err = pthread_key_create(&keys_[i], 0);
+ if (err) {
+ fprintf(stderr, "pthread_key_create failed with %d\n", err);
+ exit(1);
+ }
+ }
+ for (size_t i = 0; i < N; i++)
+ pthread_setspecific(keys_[i], (void*)(long)i);
+ for (size_t i = 0; i < N; i++)
+ pthread_key_delete(keys_[i]);
+ return 0;
+}
+
+int main() {
+ for (int i = 0; i < 10; i++) {
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ pthread_join(th, 0);
+ }
+ pthread_t th[2];
+ pthread_create(&th[0], 0, thr, 0);
+ pthread_create(&th[1], 0, thr, 0);
+ pthread_join(th[0], 0);
+ pthread_join(th[1], 0);
+ fprintf(stderr, "DONE\n");
+ // CHECK: DONE
+}
More information about the llvm-commits
mailing list