From cd07898cf89f0a360855e74de6d7a86784aab82a Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Wed, 11 Dec 2013 10:55:42 +0000 Subject: [PATCH] [msan] Get stack limits with pthread_create interceptor. Before we did it lazily on the first stack unwind in the thread. It resulted in deadlock when the unwind was caused by memory allocation inside pthread_getattr_np: pthread_getattr_np <<< not reentable GetThreadStackTopAndBottom __interceptor_realloc pthread_getattr_np llvm-svn: 197026 --- .../lit_tests/pthread_getattr_np_deadlock.cc | 22 +++++++++++++++ compiler-rt/lib/msan/msan.cc | 28 ++++--------------- compiler-rt/lib/msan/msan.h | 6 ++++ compiler-rt/lib/msan/msan_interceptors.cc | 4 +++ 4 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 compiler-rt/lib/msan/lit_tests/pthread_getattr_np_deadlock.cc diff --git a/compiler-rt/lib/msan/lit_tests/pthread_getattr_np_deadlock.cc b/compiler-rt/lib/msan/lit_tests/pthread_getattr_np_deadlock.cc new file mode 100644 index 000000000000..44dfc19b9564 --- /dev/null +++ b/compiler-rt/lib/msan/lit_tests/pthread_getattr_np_deadlock.cc @@ -0,0 +1,22 @@ +// RUN: %clangxx_msan -m64 -fsanitize-memory-track-origins -O0 %s -o %t && %t + +// Regression test for a deadlock in pthread_getattr_np + +#include +#include + +void *ThreadFn(void *) { + pthread_attr_t attr; + int res = pthread_getattr_np(pthread_self(), &attr); + assert(!res); + return 0; +} + +int main(void) { + pthread_t t; + int res = pthread_create(&t, 0, ThreadFn, 0); + assert(!res); + res = pthread_join(t, 0); + assert(!res); + return 0; +} diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index 315b677cbc25..ecc7cb82817b 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -59,9 +59,7 @@ THREADLOCAL u64 __msan_va_arg_overflow_size_tls; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __msan_origin_tls; -static THREADLOCAL struct { - uptr stack_top, stack_bottom; -} __msan_stack_bounds; +THREADLOCAL MsanStackBounds msan_stack_bounds; static THREADLOCAL int is_in_symbolizer; static THREADLOCAL int is_in_loader; @@ -168,19 +166,6 @@ static void InitializeFlags(Flags *f, const char *options) { ParseFlagsFromString(f, options); } -static void GetCurrentStackBounds(uptr *stack_top, uptr *stack_bottom) { - if (__msan_stack_bounds.stack_top == 0) { - // Break recursion (GetStackTrace -> GetThreadStackTopAndBottom -> - // realloc -> GetStackTrace). - __msan_stack_bounds.stack_top = __msan_stack_bounds.stack_bottom = 1; - GetThreadStackTopAndBottom(/* at_initialization */false, - &__msan_stack_bounds.stack_top, - &__msan_stack_bounds.stack_bottom); - } - *stack_top = __msan_stack_bounds.stack_top; - *stack_bottom = __msan_stack_bounds.stack_bottom; -} - void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool request_fast_unwind) { if (!StackTrace::WillUseFastUnwind(request_fast_unwind)) { @@ -188,9 +173,8 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, SymbolizerScope sym_scope; return stack->Unwind(max_s, pc, bp, 0, 0, request_fast_unwind); } - uptr stack_top, stack_bottom; - GetCurrentStackBounds(&stack_top, &stack_bottom); - stack->Unwind(max_s, pc, bp, stack_top, stack_bottom, request_fast_unwind); + stack->Unwind(max_s, pc, bp, msan_stack_bounds.stack_top, + msan_stack_bounds.stack_bottom, request_fast_unwind); } void PrintWarning(uptr pc, uptr bp) { @@ -340,9 +324,9 @@ void __msan_init() { } Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer); - GetThreadStackTopAndBottom(/* at_initialization */true, - &__msan_stack_bounds.stack_top, - &__msan_stack_bounds.stack_bottom); + GetThreadStackTopAndBottom(/* at_initialization */ true, + &msan_stack_bounds.stack_top, + &msan_stack_bounds.stack_bottom); VPrintf(1, "MemorySanitizer init done\n"); msan_init_is_running = 0; msan_inited = 1; diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h index 4e6c6194505e..a50540b077ba 100644 --- a/compiler-rt/lib/msan/msan.h +++ b/compiler-rt/lib/msan/msan.h @@ -106,4 +106,10 @@ class ScopedThreadLocalStateBackup { #define MSAN_FREE_HOOK(ptr) \ if (&__msan_free_hook) __msan_free_hook(ptr) +struct MsanStackBounds { + uptr stack_top, stack_bottom; +}; + +extern THREADLOCAL MsanStackBounds msan_stack_bounds; + #endif // MSAN_H diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index 873d72ec2f3f..5dc12af660eb 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -1088,6 +1088,10 @@ static void *MsanThreadStartFunc(void *arg) { Die(); } atomic_store(&p->done, 1, memory_order_release); + + GetThreadStackTopAndBottom(/* at_initialization */ false, + &msan_stack_bounds.stack_top, + &msan_stack_bounds.stack_bottom); return callback(param); }