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
Change-Id: I78cc01fbdabe169154ff6b94c9f3ddb95b5c7448
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 @@
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 @@
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 @@
}
}
+// 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 @@
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 @@
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