[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
This commit is contained in:
Evgeniy Stepanov 2013-12-11 10:55:42 +00:00
parent 338d70c0bb
commit cd07898cf8
4 changed files with 38 additions and 22 deletions

View File

@ -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 <assert.h>
#include <pthread.h>
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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}