diff options
author | Andreas Gampe <agampe@google.com> | 2015-05-22 18:31:50 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-05-31 16:59:11 -0700 |
commit | 8ee2145d65ed14b267ae4c6396f2333115611a97 (patch) | |
tree | 77c4ffa7f2b21e35e9e09bbce26306ca486f64e2 /sigchainlib | |
parent | 93de952df65ca5033bda313712b68b6272b4975f (diff) | |
download | art-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.cc | 53 | ||||
-rw-r--r-- | sigchainlib/sigchain.h | 3 | ||||
-rw-r--r-- | sigchainlib/sigchain_dummy.cc | 6 |
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 |