[compiler-rt] 00a1007 - sanitizer_common/symbolizer: fix crashes during exit

Dmitry Vyukov via llvm-commits llvm-commits at lists.llvm.org
Mon May 17 23:58:14 PDT 2021


Author: Dmitry Vyukov
Date: 2021-05-18T08:58:08+02:00
New Revision: 00a1007545ba8ad2105876a41364b35235749e2a

URL: https://github.com/llvm/llvm-project/commit/00a1007545ba8ad2105876a41364b35235749e2a
DIFF: https://github.com/llvm/llvm-project/commit/00a1007545ba8ad2105876a41364b35235749e2a.diff

LOG: sanitizer_common/symbolizer: fix crashes during exit

Override __cxa_atexit and ignore callbacks.
This prevents crashes in a configuration when the symbolizer
is built into sanitizer runtime and consequently into the test process.
LLVM libraries have some global objects destroyed during exit,
so if the test process triggers any bugs after that, the symbolizer crashes.
An example stack trace of such crash:

For the standalone llvm-symbolizer this does not hurt,
we just don't destroy few global objects on exit.

Reviewed By: kda

Differential Revision: https://reviews.llvm.org/D102470

Added: 
    compiler-rt/test/tsan/atexit4.cpp

Modified: 
    compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp b/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp
index 58f903d419ff8..3809880d50b4a 100644
--- a/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp
+++ b/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp
@@ -105,4 +105,32 @@ int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
              : 0;
 }
 
+// Override __cxa_atexit and ignore callbacks.
+// This prevents crashes in a configuration when the symbolizer
+// is built into sanitizer runtime and consequently into the test process.
+// LLVM libraries have some global objects destroyed during exit,
+// so if the test process triggers any bugs after that, the symbolizer crashes.
+// An example stack trace of such crash:
+//
+// #1  __cxa_throw
+// #2  std::__u::__throw_system_error
+// #3  std::__u::recursive_mutex::lock
+// #4  __sanitizer_llvm::ManagedStaticBase::RegisterManagedStatic
+// #5  __sanitizer_llvm::errorToErrorCode
+// #6  __sanitizer_llvm::getFileAux
+// #7  __sanitizer_llvm::MemoryBuffer::getFileOrSTDIN
+// #10 __sanitizer_llvm::symbolize::LLVMSymbolizer::getOrCreateModuleInfo
+// #13 __sanitizer::Symbolizer::SymbolizeData
+// #14 __tsan::SymbolizeData
+// #16 __tsan::ReportRace
+// #18 __tsan_write4
+// #19 race() () at test/tsan/atexit4.cpp
+// #20 cxa_at_exit_wrapper
+// #21 __cxa_finalize
+// #22 __do_fini
+//
+// For the standalone llvm-symbolizer this does not hurt,
+// we just don't destroy few global objects on exit.
+int __cxa_atexit(void (*f)(void *a), void *arg, void *dso) { return 0; }
+
 }  // extern "C"

diff  --git a/compiler-rt/test/tsan/atexit4.cpp b/compiler-rt/test/tsan/atexit4.cpp
new file mode 100644
index 0000000000000..893f7b4be2519
--- /dev/null
+++ b/compiler-rt/test/tsan/atexit4.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+#include "test.h"
+
+void *thread(void *x) {
+  barrier_wait(&barrier);
+  *static_cast<int *>(x) = 2;
+  return nullptr;
+}
+
+static void race() {
+  int data = 0;
+  pthread_t t;
+  pthread_create(&t, nullptr, thread, &data);
+  data = 1;
+  barrier_wait(&barrier);
+  pthread_join(t, nullptr);
+}
+
+struct X {
+  X() { atexit(race); }
+} x;
+
+int main() {
+  barrier_init(&barrier, 2);
+  fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE
+// CHECK: WARNING: ThreadSanitizer: data race


        


More information about the llvm-commits mailing list