diff options
| -rw-r--r-- | sigchainlib/sigchain.cc | 8 | ||||
| -rw-r--r-- | test/115-native-bridge/nativebridge.cc | 31 |
2 files changed, 39 insertions, 0 deletions
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index c984b17c2c..b76555b00b 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -150,10 +150,15 @@ extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context) // Do we have a managed handler? If so, run it first. SpecialSignalHandlerFn managed = user_sigactions[sig].GetSpecialHandler(); if (managed != nullptr) { + sigset_t mask, old_mask; + sigfillset(&mask); + sigprocmask(SIG_BLOCK, &mask, &old_mask); // Call the handler. If it succeeds, we're done. if (managed(sig, info, context)) { + sigprocmask(SIG_SETMASK, &old_mask, nullptr); return; } + sigprocmask(SIG_SETMASK, &old_mask, nullptr); } const struct sigaction& action = user_sigactions[sig].GetAction(); @@ -166,7 +171,10 @@ extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context) } } else { if (action.sa_sigaction != nullptr) { + sigset_t old_mask; + sigprocmask(SIG_BLOCK, &action.sa_mask, &old_mask); action.sa_sigaction(sig, info, context); + sigprocmask(SIG_SETMASK, &old_mask, nullptr); } else { signal(sig, SIG_DFL); raise(sig); diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc index 948273abd5..e9946c885c 100644 --- a/test/115-native-bridge/nativebridge.cc +++ b/test/115-native-bridge/nativebridge.cc @@ -390,6 +390,20 @@ extern "C" bool nb_is_compatible(uint32_t bridge_version ATTRIBUTE_UNUSED) { #endif #endif +static bool cannot_be_blocked(int signum) { + // These two sigs cannot be blocked anywhere. + if ((signum == SIGKILL) || (signum == SIGSTOP)) { + return true; + } + + // The invalid rt_sig cannot be blocked. + if (((signum >= 32) && (signum < SIGRTMIN)) || (signum > SIGRTMAX)) { + return true; + } + + return false; +} + // A dummy special handler, continueing after the faulting location. This code comes from // 004-SignalTest. static bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* context) { @@ -413,6 +427,23 @@ static bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* co UNUSED(context); #endif } + + // Before invoking this handler, all other unclaimed signals must be blocked. + // We're trying to check the signal mask to verify its status here. + sigset_t tmpset; + sigemptyset(&tmpset); + sigprocmask(SIG_SETMASK, nullptr, &tmpset); + int other_claimed = (sig == SIGSEGV) ? SIGILL : SIGSEGV; + for (int signum = 0; signum < NSIG; ++signum) { + if (cannot_be_blocked(signum)) { + continue; + } else if ((sigismember(&tmpset, signum)) && (signum == other_claimed)) { + printf("ERROR: The claimed signal %d is blocked\n", signum); + } else if ((!sigismember(&tmpset, signum)) && (signum != other_claimed)) { + printf("ERROR: The unclaimed signal %d is not blocked\n", signum); + } + } + // We handled this... return true; } |