[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