[compiler-rt] r257975 - [LSan] Ignore all allocations made inside pthread_create.

Alexey Samsonov via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 15 16:57:25 PST 2016


Author: samsonov
Date: Fri Jan 15 18:57:25 2016
New Revision: 257975

URL: http://llvm.org/viewvc/llvm-project?rev=257975&view=rev
Log:
[LSan] Ignore all allocations made inside pthread_create.

Thread stack/TLS may be stored by libpthread for future reuse after
thread destruction, and the linked list it's stored in doesn't
even hold valid pointers to the objects, the latter are calculated
by obscure pointer arithmetic.

With this change applied, LSan test suite passes with
"use_ld_allocations" flag defaulted to "false". It still requires more
testing to check if the default can be switched.

Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/lsan/lsan_common.cc
    compiler-rt/trunk/lib/lsan/lsan_common.h
    compiler-rt/trunk/lib/lsan/lsan_interceptors.cc
    compiler-rt/trunk/test/lsan/TestCases/disabler_in_tsd_destructor.c
    compiler-rt/trunk/test/lsan/TestCases/high_allocator_contention.cc

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=257975&r1=257974&r2=257975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri Jan 15 18:57:25 2016
@@ -21,6 +21,7 @@
 #include "asan_stack.h"
 #include "asan_stats.h"
 #include "asan_suppressions.h"
+#include "lsan/lsan_common.h"
 #include "sanitizer_common/sanitizer_libc.h"
 
 #if SANITIZER_POSIX
@@ -242,7 +243,17 @@ INTERCEPTOR(int, pthread_create, void *t
   ThreadStartParam param;
   atomic_store(&param.t, 0, memory_order_relaxed);
   atomic_store(&param.is_registered, 0, memory_order_relaxed);
-  int result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
+  int result;
+  {
+    // Ignore all allocations made by pthread_create: thread stack/TLS may be
+    // stored by pthread for future reuse even after thread destruction, and
+    // the linked list it's stored in doesn't even hold valid pointers to the
+    // objects, the latter are calculated by obscure pointer arithmetic.
+#if CAN_SANITIZE_LEAKS
+    __lsan::ScopedInterceptorDisabler disabler;
+#endif
+    result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
+  }
   if (result == 0) {
     u32 current_tid = GetCurrentTidOrInvalid();
     AsanThread *t =

Modified: compiler-rt/trunk/lib/lsan/lsan_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=257975&r1=257974&r2=257975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc Fri Jan 15 18:57:25 2016
@@ -34,6 +34,14 @@ BlockingMutex global_mutex(LINKER_INITIA
 
 THREADLOCAL int disable_counter;
 bool DisabledInThisThread() { return disable_counter > 0; }
+void DisableInThisThread() { disable_counter++; }
+void EnableInThisThread() {
+  if (!disable_counter && common_flags()->detect_leaks) {
+    Report("Unmatched call to __lsan_enable().\n");
+    Die();
+  }
+  disable_counter--;
+}
 
 Flags lsan_flags;
 
@@ -695,18 +703,14 @@ void __lsan_unregister_root_region(const
 SANITIZER_INTERFACE_ATTRIBUTE
 void __lsan_disable() {
 #if CAN_SANITIZE_LEAKS
-  __lsan::disable_counter++;
+  __lsan::DisableInThisThread();
 #endif
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void __lsan_enable() {
 #if CAN_SANITIZE_LEAKS
-  if (!__lsan::disable_counter && common_flags()->detect_leaks) {
-    Report("Unmatched call to __lsan_enable().\n");
-    Die();
-  }
-  __lsan::disable_counter--;
+  __lsan::EnableInThisThread();
 #endif
 }
 

Modified: compiler-rt/trunk/lib/lsan/lsan_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.h?rev=257975&r1=257974&r2=257975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.h (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.h Fri Jan 15 18:57:25 2016
@@ -119,6 +119,16 @@ void InitCommonLsan();
 void DoLeakCheck();
 bool DisabledInThisThread();
 
+// Used to implement __lsan::ScopedDisabler.
+void DisableInThisThread();
+void EnableInThisThread();
+// Can be used to ignore memory allocated by an intercepted
+// function.
+struct ScopedInterceptorDisabler {
+  ScopedInterceptorDisabler() { DisableInThisThread(); }
+  ~ScopedInterceptorDisabler() { EnableInThisThread(); }
+};
+
 // Special case for "new T[0]" where T is a type with DTOR.
 // new T[0] will allocate one word for the array size (0) and store a pointer
 // to the end of allocated chunk.

Modified: compiler-rt/trunk/lib/lsan/lsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_interceptors.cc?rev=257975&r1=257974&r2=257975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_interceptors.cc Fri Jan 15 18:57:25 2016
@@ -23,6 +23,7 @@
 #include "sanitizer_common/sanitizer_tls_get_addr.h"
 #include "lsan.h"
 #include "lsan_allocator.h"
+#include "lsan_common.h"
 #include "lsan_thread.h"
 
 using namespace __lsan;
@@ -241,7 +242,15 @@ INTERCEPTOR(int, pthread_create, void *t
   p.callback = callback;
   p.param = param;
   atomic_store(&p.tid, 0, memory_order_relaxed);
-  int res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
+  int res;
+  {
+    // Ignore all allocations made by pthread_create: thread stack/TLS may be
+    // stored by pthread for future reuse even after thread destruction, and
+    // the linked list it's stored in doesn't even hold valid pointers to the
+    // objects, the latter are calculated by obscure pointer arithmetic.
+    ScopedInterceptorDisabler disabler;
+    res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
+  }
   if (res == 0) {
     int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th, detached);
     CHECK_NE(tid, 0);

Modified: compiler-rt/trunk/test/lsan/TestCases/disabler_in_tsd_destructor.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/disabler_in_tsd_destructor.c?rev=257975&r1=257974&r2=257975&view=diff
==============================================================================
--- compiler-rt/trunk/test/lsan/TestCases/disabler_in_tsd_destructor.c (original)
+++ compiler-rt/trunk/test/lsan/TestCases/disabler_in_tsd_destructor.c Fri Jan 15 18:57:25 2016
@@ -1,5 +1,5 @@
 // Regression test. Disabler should not depend on TSD validity.
-// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=1"
+// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=1:use_ld_allocations=0"
 // RUN: %clang_lsan %s -o %t
 // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t
 

Modified: compiler-rt/trunk/test/lsan/TestCases/high_allocator_contention.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/high_allocator_contention.cc?rev=257975&r1=257974&r2=257975&view=diff
==============================================================================
--- compiler-rt/trunk/test/lsan/TestCases/high_allocator_contention.cc (original)
+++ compiler-rt/trunk/test/lsan/TestCases/high_allocator_contention.cc Fri Jan 15 18:57:25 2016
@@ -1,7 +1,8 @@
 // A benchmark that executes malloc/free pairs in parallel.
 // Usage: ./a.out number_of_threads total_number_of_allocations
+// RUN: LSAN_BASE="use_ld_allocations=0"
 // RUN: %clangxx_lsan %s -o %t
-// RUN: %run %t 5 1000000 2>&1
+// RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 5 1000000 2>&1
 #include <assert.h>
 #include <pthread.h>
 #include <stdlib.h>




More information about the llvm-commits mailing list