summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorJosh Gao <jmgao@google.com>2017-03-20 16:26:42 -0700
committerJosh Gao <jmgao@google.com>2017-03-23 16:16:53 -0700
commit85a78cff8cbd6477c19ab4c9a21698dddcf0a9f9 (patch)
treecee518d7bed60fcc3c4c08603f27500a8d2e6eea /runtime
parent6efac9929f8952e4871e8c423c923989fc6f2ad2 (diff)
downloadart-85a78cff8cbd6477c19ab4c9a21698dddcf0a9f9.tar.gz
art-85a78cff8cbd6477c19ab4c9a21698dddcf0a9f9.tar.bz2
art-85a78cff8cbd6477c19ab4c9a21698dddcf0a9f9.zip
Revert^2: "Make sigchain actually own the signal chain.""
This reverts commit 33dca562d5ed9f52f63ced2334c066333ca073e9. Bug: http://b/36205469 Bug: http://b/36262089 Original-Change-Id: I416b13de800d3e23424cf20688ccfd7e4e48a111 Change-Id: I1267be72c32ed73d1079a572d0b8907556526dde
Diffstat (limited to 'runtime')
-rw-r--r--runtime/fault_handler.cc131
-rw-r--r--runtime/fault_handler.h4
-rw-r--r--runtime/java_vm_ext.cc4
-rw-r--r--runtime/native_bridge_art_interface.cc2
4 files changed, 29 insertions, 112 deletions
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 64128cc61e..4220250c38 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -38,8 +38,8 @@ extern "C" __attribute__((visibility("default"))) void art_sigsegv_fault() {
}
// Signal handler called on SIGSEGV.
-static void art_fault_handler(int sig, siginfo_t* info, void* context) {
- fault_manager.HandleFault(sig, info, context);
+static bool art_fault_handler(int sig, siginfo_t* info, void* context) {
+ return fault_manager.HandleFault(sig, info, context);
}
FaultManager::FaultManager() : initialized_(false) {
@@ -49,43 +49,15 @@ FaultManager::FaultManager() : initialized_(false) {
FaultManager::~FaultManager() {
}
-static void SetUpArtAction(struct sigaction* action) {
- action->sa_sigaction = art_fault_handler;
- sigemptyset(&action->sa_mask);
- action->sa_flags = SA_SIGINFO | SA_ONSTACK;
-#if !defined(__APPLE__) && !defined(__mips__)
- action->sa_restorer = nullptr;
-#endif
-}
-
-void FaultManager::EnsureArtActionInFrontOfSignalChain() {
- if (initialized_) {
- struct sigaction action;
- SetUpArtAction(&action);
- EnsureFrontOfChain(SIGSEGV, &action);
- } else {
- LOG(WARNING) << "Can't call " << __FUNCTION__ << " due to unitialized fault manager";
- }
-}
-
void FaultManager::Init() {
CHECK(!initialized_);
- struct sigaction action;
- SetUpArtAction(&action);
-
- // Set our signal handler now.
- int e = sigaction(SIGSEGV, &action, &oldaction_);
- if (e != 0) {
- VLOG(signals) << "Failed to claim SEGV: " << strerror(errno);
- }
- // Make sure our signal handler is called before any user handlers.
- ClaimSignalChain(SIGSEGV, &oldaction_);
+ AddSpecialSignalHandlerFn(SIGSEGV, art_fault_handler);
initialized_ = true;
}
void FaultManager::Release() {
if (initialized_) {
- UnclaimSignalChain(SIGSEGV);
+ RemoveSpecialSignalHandlerFn(SIGSEGV, art_fault_handler);
initialized_ = false;
}
}
@@ -118,93 +90,36 @@ bool FaultManager::HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* co
return false;
}
-class ScopedSignalUnblocker {
- public:
- explicit ScopedSignalUnblocker(const std::initializer_list<int>& signals) {
- sigset_t new_mask;
- sigemptyset(&new_mask);
- for (int signal : signals) {
- sigaddset(&new_mask, signal);
- }
- if (sigprocmask(SIG_UNBLOCK, &new_mask, &previous_mask_) != 0) {
- PLOG(FATAL) << "failed to unblock signals";
- }
- }
-
- ~ScopedSignalUnblocker() {
- if (sigprocmask(SIG_SETMASK, &previous_mask_, nullptr) != 0) {
- PLOG(FATAL) << "failed to unblock signals";
- }
- }
-
- private:
- sigset_t previous_mask_;
-};
-
-class ScopedHandlingSignalSetter {
- public:
- explicit ScopedHandlingSignalSetter(Thread* thread) : thread_(thread) {
- CHECK(!thread->HandlingSignal());
- thread_->SetHandlingSignal(true);
- }
-
- ~ScopedHandlingSignalSetter() {
- CHECK(thread_->HandlingSignal());
- thread_->SetHandlingSignal(false);
- }
-
- private:
- Thread* thread_;
-};
-
-void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
- // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)
- //
- // If malloc calls abort, it will be holding its lock.
- // If the handler tries to call malloc, it will deadlock.
-
- // Use a thread local field to track whether we're recursing, and fall back.
- // (e.g.. if one of our handlers crashed)
- Thread* thread = Thread::Current();
-
- if (thread != nullptr && !thread->HandlingSignal()) {
- // Unblock some signals and set thread->handling_signal_ to true,
- // so that we can catch crashes in our signal handler.
- ScopedHandlingSignalSetter setter(thread);
- ScopedSignalUnblocker unblocker { SIGABRT, SIGBUS, SIGSEGV }; // NOLINT
-
- VLOG(signals) << "Handling fault";
+bool FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
+ VLOG(signals) << "Handling fault";
#ifdef TEST_NESTED_SIGNAL
- // Simulate a crash in a handler.
- raise(SIGSEGV);
+ // Simulate a crash in a handler.
+ raise(SIGSEGV);
#endif
- if (IsInGeneratedCode(info, context, true)) {
- VLOG(signals) << "in generated code, looking for handler";
- for (const auto& handler : generated_code_handlers_) {
- VLOG(signals) << "invoking Action on handler " << handler;
- if (handler->Action(sig, info, context)) {
- // We have handled a signal so it's time to return from the
- // signal handler to the appropriate place.
- return;
- }
+ if (IsInGeneratedCode(info, context, true)) {
+ VLOG(signals) << "in generated code, looking for handler";
+ for (const auto& handler : generated_code_handlers_) {
+ VLOG(signals) << "invoking Action on handler " << handler;
+ if (handler->Action(sig, info, context)) {
+ // We have handled a signal so it's time to return from the
+ // signal handler to the appropriate place.
+ return true;
}
+ }
- // We hit a signal we didn't handle. This might be something for which
- // we can give more information about so call all registered handlers to
- // see if it is.
- if (HandleFaultByOtherHandlers(sig, info, context)) {
- return;
- }
+ // We hit a signal we didn't handle. This might be something for which
+ // we can give more information about so call all registered handlers to
+ // see if it is.
+ if (HandleFaultByOtherHandlers(sig, info, context)) {
+ return true;
}
}
// Set a breakpoint in this function to catch unhandled signals.
art_sigsegv_fault();
-
- // Pass this on to the next handler in the chain, or the default if none.
- InvokeUserSignalHandler(sig, info, context);
+ return false;
}
void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) {
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h
index ce59ba7e64..d56cf17861 100644
--- a/runtime/fault_handler.h
+++ b/runtime/fault_handler.h
@@ -42,9 +42,9 @@ class FaultManager {
// Unclaim signals and delete registered handlers.
void Shutdown();
- void EnsureArtActionInFrontOfSignalChain();
- void HandleFault(int sig, siginfo_t* info, void* context);
+ // Try to handle a fault, returns true if successful.
+ bool HandleFault(int sig, siginfo_t* info, void* context);
// Added handlers are owned by the fault handler and will be freed on Shutdown().
void AddHandler(FaultHandler* handler, bool generated_code);
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index a341cdb89f..b93b8f2a97 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -39,6 +39,7 @@
#include "runtime_options.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change-inl.h"
+#include "sigchain.h"
#include "thread-inl.h"
#include "thread_list.h"
@@ -900,7 +901,8 @@ bool JavaVMExt::LoadNativeLibrary(JNIEnv* env,
int version = (*jni_on_load)(this, nullptr);
if (runtime_->GetTargetSdkVersion() != 0 && runtime_->GetTargetSdkVersion() <= 21) {
- fault_manager.EnsureArtActionInFrontOfSignalChain();
+ // Make sure that sigchain owns SIGSEGV.
+ EnsureFrontOfChain(SIGSEGV);
}
self->SetClassLoaderOverride(old_class_loader.get());
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
index c58854b13e..d77cfa1d35 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -118,7 +118,7 @@ void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
for (int signal = 0; signal < _NSIG; ++signal) {
android::NativeBridgeSignalHandlerFn fn = android::NativeBridgeGetSignalHandler(signal);
if (fn != nullptr) {
- SetSpecialSignalHandlerFn(signal, fn);
+ AddSpecialSignalHandlerFn(signal, fn);
}
}
#endif