diff options
Diffstat (limited to 'sigchainlib/sigchain.cc')
-rw-r--r-- | sigchainlib/sigchain.cc | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index c5015e8..601e321 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -35,6 +35,8 @@ namespace art { +typedef int (*SigActionFnPtr)(int, const struct sigaction*, struct sigaction*); + class SignalAction { public: SignalAction() : claimed_(false), uses_old_style_(false) { @@ -147,7 +149,20 @@ extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context) } } -// These functions are C linkage since they replace the functions in libc. +extern "C" 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" int sigaction(int signal, const struct sigaction* new_action, struct sigaction* old_action) { // If this signal has been claimed as a signal chain, record the user's @@ -179,9 +194,7 @@ extern "C" int sigaction(int signal, const struct sigaction* new_action, struct 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); } @@ -287,5 +300,6 @@ extern "C" void InitializeSignalChain() { } initialized = true; } + } // namespace art |