summaryrefslogtreecommitdiffstats
path: root/sigchainlib
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-05-22 18:31:50 -0700
committerAndreas Gampe <agampe@google.com>2015-05-31 16:59:11 -0700
commit8ee2145d65ed14b267ae4c6396f2333115611a97 (patch)
tree77c4ffa7f2b21e35e9e09bbce26306ca486f64e2 /sigchainlib
parent93de952df65ca5033bda313712b68b6272b4975f (diff)
downloadart-8ee2145d65ed14b267ae4c6396f2333115611a97.zip
art-8ee2145d65ed14b267ae4c6396f2333115611a97.tar.gz
art-8ee2145d65ed14b267ae4c6396f2333115611a97.tar.bz2
ART: Add support for special handlers in sigchainlib
Add support for a special managed handler in sigchainlib that will be called as the first user handler. Use this support for native bridge v2. Extend test 115-native-bridge to test the functionality. Bug: 20217701 (cherry picked from commit 03c2cc89428914adf52229d6a3867eef6127911a) Change-Id: I78cc01fbdabe169154ff6b94c9f3ddb95b5c7448
Diffstat (limited to 'sigchainlib')
-rw-r--r--sigchainlib/sigchain.cc53
-rw-r--r--sigchainlib/sigchain.h3
-rw-r--r--sigchainlib/sigchain_dummy.cc6
3 files changed, 58 insertions, 4 deletions
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index 0359ed3..1391d14 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -39,7 +39,7 @@ typedef int (*SigActionFnPtr)(int, const struct sigaction*, struct sigaction*);
class SignalAction {
public:
- SignalAction() : claimed_(false), uses_old_style_(false) {
+ SignalAction() : claimed_(false), uses_old_style_(false), special_handler_(nullptr) {
}
// Claim the signal and keep the action specified.
@@ -77,10 +77,19 @@ class SignalAction {
return uses_old_style_;
}
+ void SetSpecialHandler(SpecialSignalHandlerFn fn) {
+ special_handler_ = fn;
+ }
+
+ SpecialSignalHandlerFn GetSpecialHandler() {
+ return special_handler_;
+ }
+
private:
- struct sigaction action_; // Action to be performed.
- bool claimed_; // Whether signal is claimed or not.
- bool uses_old_style_; // Action is created using signal(). Use sa_handler.
+ struct sigaction action_; // Action to be performed.
+ bool claimed_; // Whether signal is claimed or not.
+ bool uses_old_style_; // Action is created using signal(). Use sa_handler.
+ SpecialSignalHandlerFn special_handler_; // A special handler executed before user handlers.
};
// User's signal handlers
@@ -109,9 +118,16 @@ static void CheckSignalValid(int signal) {
}
}
+// Sigchainlib's own handler so we can ensure a managed handler is called first even if nobody
+// claimed a chain. Simply forward to InvokeUserSignalHandler.
+static void sigchainlib_managed_handler_sigaction(int sig, siginfo_t* info, void* context) {
+ InvokeUserSignalHandler(sig, info, context);
+}
+
// Claim a signal chain for a particular signal.
extern "C" void ClaimSignalChain(int signal, struct sigaction* oldaction) {
CheckSignalValid(signal);
+
user_sigactions[signal].Claim(*oldaction);
}
@@ -131,6 +147,15 @@ extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context)
abort();
}
+ // Do we have a managed handler? If so, run it first.
+ SpecialSignalHandlerFn managed = user_sigactions[sig].GetSpecialHandler();
+ if (managed != nullptr) {
+ // Call the handler. If it succeeds, we're done.
+ if (managed(sig, info, context)) {
+ return;
+ }
+ }
+
const struct sigaction& action = user_sigactions[sig].GetAction();
if (user_sigactions[sig].OldStyle()) {
if (action.sa_handler != nullptr) {
@@ -303,5 +328,25 @@ extern "C" void InitializeSignalChain() {
initialized = true;
}
+extern "C" void SetSpecialSignalHandlerFn(int signal, SpecialSignalHandlerFn fn) {
+ CheckSignalValid(signal);
+
+ // Set the managed_handler.
+ user_sigactions[signal].SetSpecialHandler(fn);
+
+ // In case the chain isn't claimed, claim it for ourself so we can ensure the managed handler
+ // goes first.
+ if (!user_sigactions[signal].IsClaimed()) {
+ struct sigaction tmp;
+ tmp.sa_sigaction = sigchainlib_managed_handler_sigaction;
+ sigemptyset(&tmp.sa_mask);
+ tmp.sa_flags = SA_SIGINFO | SA_ONSTACK;
+#if !defined(__APPLE__) && !defined(__mips__)
+ tmp.sa_restorer = nullptr;
+#endif
+ user_sigactions[signal].Claim(tmp);
+ }
+}
+
} // namespace art
diff --git a/sigchainlib/sigchain.h b/sigchainlib/sigchain.h
index 79b76a7..01ccedf 100644
--- a/sigchainlib/sigchain.h
+++ b/sigchainlib/sigchain.h
@@ -27,6 +27,9 @@ extern "C" void ClaimSignalChain(int signal, struct sigaction* oldaction);
extern "C" void UnclaimSignalChain(int signal);
+typedef bool (*SpecialSignalHandlerFn)(int, siginfo_t*, void*);
+extern "C" void SetSpecialSignalHandlerFn(int signal, SpecialSignalHandlerFn fn);
+
extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context);
extern "C" void EnsureFrontOfChain(int signal, struct sigaction* expected_action);
diff --git a/sigchainlib/sigchain_dummy.cc b/sigchainlib/sigchain_dummy.cc
index 70a4f71..8495a54 100644
--- a/sigchainlib/sigchain_dummy.cc
+++ b/sigchainlib/sigchain_dummy.cc
@@ -78,6 +78,12 @@ extern "C" void EnsureFrontOfChain(int signal ATTRIBUTE_UNUSED,
abort();
}
+extern "C" void SetSpecialSignalHandlerFn(int signal ATTRIBUTE_UNUSED,
+ SpecialSignalHandlerFn fn ATTRIBUTE_UNUSED) {
+ log("SetSpecialSignalHandlerFn is not exported by the main executable.");
+ abort();
+}
+
#pragma GCC diagnostic pop
} // namespace art