[PATCH] [sanitizer] Handle Die() in StopTheWorld.

Sergey Matveev earthdok at google.com
Mon Aug 26 04:24:13 PDT 2013


Hi kcc,

Handle calls to Die() from the tracer thread. Fixes a bug where a CHECK
could fail in the tracer thread, resulting in a call to AsanDie. The tracer
thread then exited and the parent process continued execution despite its
address space being in an unusable state.

http://llvm-reviews.chandlerc.com/D1515

Files:
  lib/sanitizer_common/sanitizer_common.cc
  lib/sanitizer_common/sanitizer_common.h
  lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc

Index: lib/sanitizer_common/sanitizer_common.cc
===================================================================
--- lib/sanitizer_common/sanitizer_common.cc
+++ lib/sanitizer_common/sanitizer_common.cc
@@ -37,11 +37,15 @@
 // child thread will be different from |report_fd_pid|.
 static uptr report_fd_pid = 0;
 
-static void (*DieCallback)(void);
-void SetDieCallback(void (*callback)(void)) {
+static DieCallbackType DieCallback;
+void SetDieCallback(DieCallbackType callback) {
   DieCallback = callback;
 }
 
+DieCallbackType GetDieCallback() {
+  return DieCallback;
+}
+
 void NORETURN Die() {
   if (DieCallback) {
     DieCallback();
Index: lib/sanitizer_common/sanitizer_common.h
===================================================================
--- lib/sanitizer_common/sanitizer_common.h
+++ lib/sanitizer_common/sanitizer_common.h
@@ -165,7 +165,9 @@
 
 // Specific tools may override behavior of "Die" and "CheckFailed" functions
 // to do tool-specific job.
-void SetDieCallback(void (*callback)(void));
+typedef void (*DieCallbackType)(void);
+void SetDieCallback(DieCallbackType);
+DieCallbackType GetDieCallback();
 typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
                                        u64, u64);
 void SetCheckFailedCallback(CheckFailedCallbackType callback);
Index: lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -191,17 +191,31 @@
   BlockingMutex mutex;
 };
 
+DieCallbackType old_die_callback;
+
 // Signal handler to wake up suspended threads when the tracer thread dies.
 void TracerThreadSignalHandler(int signum, siginfo_t *siginfo, void *) {
   if (thread_suspender_instance != NULL) {
     if (signum == SIGABRT)
       thread_suspender_instance->KillAllThreads();
     else
       thread_suspender_instance->ResumeAllThreads();
   }
+  SetDieCallback(old_die_callback);
   internal__exit((signum == SIGABRT) ? 1 : 2);
 }
 
+void DieCallback() {
+  // This really only works correctly if all the threads are suspended at this
+  // point. So we correctly handle calls to Die() from within the callback, but
+  // not those that happen before or after the callback. Hopefully there aren't
+  // a lot of opportunities for that to happen...
+  if (thread_suspender_instance)
+    thread_suspender_instance->KillAllThreads();
+  if (old_die_callback)
+    old_die_callback();
+}
+
 // Size of alternative stack for signal handlers in the tracer thread.
 static const int kHandlerStackSize = 4096;
 
@@ -214,6 +228,9 @@
   tracer_thread_argument->mutex.Lock();
   tracer_thread_argument->mutex.Unlock();
 
+  old_die_callback = GetDieCallback();
+  SetDieCallback(DieCallback);
+
   ThreadSuspender thread_suspender(internal_getppid());
   // Global pointer for the signal handler.
   thread_suspender_instance = &thread_suspender;
@@ -251,6 +268,7 @@
   thread_suspender_instance = NULL;
   handler_stack.ss_flags = SS_DISABLE;
   internal_sigaltstack(&handler_stack, NULL);
+  SetDieCallback(old_die_callback);
   return exit_code;
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1515.1.patch
Type: text/x-patch
Size: 3227 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130826/f35312c2/attachment.bin>


More information about the llvm-commits mailing list