summaryrefslogtreecommitdiff
path: root/runtime/fault_handler.cc
diff options
context:
space:
mode:
author Dave Allison <dallison@google.com> 2014-05-14 15:41:25 -0700
committer Dave Allison <dallison@google.com> 2014-05-29 08:22:38 -0700
commitf4b80bcc7190fe75023b983d56a795b440a0c515 (patch)
treef2858dab6a756444755b79e36467d6c9e15060f1 /runtime/fault_handler.cc
parentc774bd435e95e537ca578486f687651fabe97008 (diff)
Make use of sigchainlib for signal chaining for implicit checks
This adds a preload library that overrides sigaction and sigprocmask to implement signal chaining. Signal chaining allows us to chain any signal so that the ART runtime receives it before any signal handler registered in native code by an application. If the ART signal handler doesn't want it, it will pass it on to the user's handler. ART uses signals for null pointer checks, stack overflow checks and suspend points. Also adds an OAT test to test this in isolation. Change-Id: I9545f9f7343774c091410eb810504d9855fd399f
Diffstat (limited to 'runtime/fault_handler.cc')
-rw-r--r--runtime/fault_handler.cc27
1 files changed, 26 insertions, 1 deletions
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 8d750c5bdd..15c38c1f4b 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -29,12 +29,22 @@
#include "mirror/object-inl.h"
#include "object_utils.h"
#include "scoped_thread_state_change.h"
+#ifdef HAVE_ANDROID_OS
+#include "sigchain.h"
+#endif
#include "verify_object-inl.h"
namespace art {
// Static fault manger object accessed by signal handler.
FaultManager fault_manager;
+extern "C" {
+void art_sigsegv_fault() {
+ // Set a breakpoint here to be informed when a SIGSEGV is unhandled by ART.
+ VLOG(signals)<< "Caught unknown SIGSEGV in ART fault handler - chaining to next handler.";
+}
+}
+
// Signal handler called on SIGSEGV.
static void art_fault_handler(int sig, siginfo_t* info, void* context) {
fault_manager.HandleFault(sig, info, context);
@@ -45,9 +55,13 @@ FaultManager::FaultManager() {
}
FaultManager::~FaultManager() {
+#ifdef HAVE_ANDROID_OS
+ UnclaimSignalChain(SIGSEGV);
+#endif
sigaction(SIGSEGV, &oldaction_, nullptr); // Restore old handler.
}
+
void FaultManager::Init() {
struct sigaction action;
action.sa_sigaction = art_fault_handler;
@@ -56,7 +70,13 @@ void FaultManager::Init() {
#if !defined(__mips__)
action.sa_restorer = nullptr;
#endif
+
+ // Set our signal handler now.
sigaction(SIGSEGV, &action, &oldaction_);
+#ifdef HAVE_ANDROID_OS
+ // Make sure our signal handler is called before any user handlers.
+ ClaimSignalChain(SIGSEGV, &oldaction_);
+#endif
}
void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
@@ -79,8 +99,13 @@ void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
return;
}
}
- VLOG(signals)<< "Caught unknown SIGSEGV in ART fault handler";
+ art_sigsegv_fault();
+
+#ifdef HAVE_ANDROID_OS
+ InvokeUserSignalHandler(sig, info, context);
+#else
oldaction_.sa_sigaction(sig, info, context);
+#endif
}
void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) {