diff options
| author | 2014-10-17 07:29:32 +0000 | |
|---|---|---|
| committer | 2014-10-17 07:29:32 +0000 | |
| commit | 4b4af816f2c5924cc173c84bc62c12d57123442e (patch) | |
| tree | 466b5700262f7adc55e93b1f09214bbd977b0a30 | |
| parent | 1fc7a271f6c8ce844f0af67165c437c859e4e20c (diff) | |
| parent | 1f24296c7c8a6501ee2388c0d20b48f471b48660 (diff) | |
am 1f24296c: Add way to ensure we are at the front of the sigaction chain
* commit '1f24296c7c8a6501ee2388c0d20b48f471b48660':
Add way to ensure we are at the front of the sigaction chain
| -rw-r--r-- | runtime/fault_handler.cc | 26 | ||||
| -rw-r--r-- | runtime/fault_handler.h | 2 | ||||
| -rw-r--r-- | runtime/jni_internal.cc | 4 | ||||
| -rw-r--r-- | sigchainlib/sigchain.cc | 21 | ||||
| -rw-r--r-- | sigchainlib/sigchain.h | 2 |
5 files changed, 44 insertions, 11 deletions
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc index 25f87c5d48..56d709ad2a 100644 --- a/runtime/fault_handler.cc +++ b/runtime/fault_handler.cc @@ -94,16 +94,29 @@ 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; - 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 + SetUpArtAction(&action); // Set our signal handler now. int e = sigaction(SIGSEGV, &action, &oldaction_); @@ -127,7 +140,6 @@ void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) { // // If malloc calls abort, it will be holding its lock. // If the handler tries to call malloc, it will deadlock. - VLOG(signals) << "Handling fault"; if (IsInGeneratedCode(info, context, true)) { VLOG(signals) << "in generated code, looking for handler"; diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h index bb26780bd9..89c9360717 100644 --- a/runtime/fault_handler.h +++ b/runtime/fault_handler.h @@ -40,6 +40,7 @@ class FaultManager { void Init(); void Shutdown(); + void EnsureArtActionInFrontOfSignalChain(); void HandleFault(int sig, siginfo_t* info, void* context); void HandleNestedSignal(int sig, siginfo_t* info, void* context); @@ -121,7 +122,6 @@ class JavaStackTraceHandler FINAL : public FaultHandler { DISALLOW_COPY_AND_ASSIGN(JavaStackTraceHandler); }; - // Statically allocated so the the signal handler can Get access to it. extern FaultManager fault_manager; diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 73effca152..bdda5c8707 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -30,6 +30,7 @@ #include "base/stl_util.h" #include "class_linker-inl.h" #include "dex_file-inl.h" +#include "fault_handler.h" #include "gc_root.h" #include "gc/accounting/card_table-inl.h" #include "indirect_reference_table-inl.h" @@ -3342,6 +3343,9 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, version = (*jni_on_load)(this, nullptr); } + if (runtime->GetTargetSdkVersion() != 0 && runtime->GetTargetSdkVersion() <= 21) { + fault_manager.EnsureArtActionInFrontOfSignalChain(); + } self->SetClassLoaderOverride(old_class_loader.Get()); if (version == JNI_ERR) { diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index 386bbd608f..4991891cfd 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -34,6 +34,8 @@ namespace art { +typedef int (*SigActionFnPtr)(int, const struct sigaction*, struct sigaction*); + class SignalAction { public: SignalAction() : claimed_(false) { @@ -138,6 +140,21 @@ void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context) { } } +void EnsureFrontOfChain(int signal, struct sigaction* expected_action) { + CheckSignalValid(signal); + // Read the current action without looking at the chain, it should be the expected action. + SigActionFnPtr linked_sigaction = reinterpret_cast<SigActionFnPtr>(linked_sigaction_sym); + struct sigaction current_action; + linked_sigaction(signal, nullptr, ¤t_action); + // If the sigactions don't match then we put the current action on the chain and make ourself as + // the main action. + if (current_action.sa_sigaction != expected_action->sa_sigaction) { + log("Warning: Unexpected sigaction action found %p\n", current_action.sa_sigaction); + user_sigactions[signal].Claim(current_action); + linked_sigaction(signal, expected_action, nullptr); + } +} + extern "C" { // These functions are C linkage since they replace the functions in libc. @@ -171,9 +188,7 @@ int sigaction(int signal, const struct sigaction* new_action, struct sigaction* log("Unable to find next sigaction in signal chain"); abort(); } - - typedef int (*SigAction)(int, const struct sigaction*, struct sigaction*); - SigAction linked_sigaction = reinterpret_cast<SigAction>(linked_sigaction_sym); + SigActionFnPtr linked_sigaction = reinterpret_cast<SigActionFnPtr>(linked_sigaction_sym); return linked_sigaction(signal, new_action, old_action); } diff --git a/sigchainlib/sigchain.h b/sigchainlib/sigchain.h index 5bc4026850..be69ca4d7e 100644 --- a/sigchainlib/sigchain.h +++ b/sigchainlib/sigchain.h @@ -25,6 +25,8 @@ void InitializeSignalChain(); void ClaimSignalChain(int signal, struct sigaction* oldaction); +void EnsureFrontOfChain(int signal, struct sigaction* expected_action); + void UnclaimSignalChain(int signal); void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context); |