summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2014-10-17 07:29:32 +0000
committer Android Git Automerger <android-git-automerger@android.com> 2014-10-17 07:29:32 +0000
commit4b4af816f2c5924cc173c84bc62c12d57123442e (patch)
tree466b5700262f7adc55e93b1f09214bbd977b0a30
parent1fc7a271f6c8ce844f0af67165c437c859e4e20c (diff)
parent1f24296c7c8a6501ee2388c0d20b48f471b48660 (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.cc26
-rw-r--r--runtime/fault_handler.h2
-rw-r--r--runtime/jni_internal.cc4
-rw-r--r--sigchainlib/sigchain.cc21
-rw-r--r--sigchainlib/sigchain.h2
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, &current_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);