From 85a78cff8cbd6477c19ab4c9a21698dddcf0a9f9 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Mon, 20 Mar 2017 16:26:42 -0700 Subject: 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 --- runtime/fault_handler.cc | 131 ++++++--------------------------- runtime/fault_handler.h | 4 +- runtime/java_vm_ext.cc | 4 +- runtime/native_bridge_art_interface.cc | 2 +- 4 files changed, 29 insertions(+), 112 deletions(-) (limited to 'runtime') 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& 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 -- cgit v1.2.3