// Bad signal number: too small.
ASSERT_ERRNO_FAILURE(EINVAL, -1, fn(&set, 0));
// Bad signal number: too high.
ASSERT_ERRNO_FAILURE(EINVAL, -1, fn(&set, SIGNAL_MAX(&set) + 1));
// Good signal numbers, low and high ends of range.
ASSERT_ERRNO_SUCCESS(0, 0, fn(&set, SIGNAL_MIN()));
ASSERT_ERRNO_SUCCESS(0, 0, fn(&set, SIGNAL_MAX(&set)));
}
// There should be no pending signals.
sigset_t pending;
sigemptyset(&pending);
ASSERT_EQ(0, sigpending(&pending)); for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
EXPECT_FALSE(sigismember(&pending, i)) << i;
}
// Raise SIGALRM and check our signal handler wasn't called.
raise(SIGALRM);
ASSERT_EQ(0, g_sigsuspend_signal_handler_call_count);
// We should now have a pending SIGALRM but nothing else.
sigemptyset(&pending);
ASSERT_EQ(0, sigpending(&pending)); for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
EXPECT_EQ((i == SIGALRM), sigismember(&pending, i));
}
// Use sigsuspend to block everything except SIGALRM...
sigset_t not_SIGALRM;
sigfillset(¬_SIGALRM);
sigdelset(¬_SIGALRM, SIGALRM);
ASSERT_ERRNO_FAILURE(EINTR, -1, sigsuspend(¬_SIGALRM)); // ...and check that we now receive our pending SIGALRM.
ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count);
}
// There should be no pending signals.
sigset64_t pending;
sigemptyset64(&pending);
ASSERT_EQ(0, sigpending64(&pending)); for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
EXPECT_FALSE(sigismember64(&pending, i)) << i;
}
// Raise SIGRTMIN and check our signal handler wasn't called.
raise(SIGRTMIN);
ASSERT_EQ(0, g_sigsuspend64_signal_handler_call_count);
// We should now have a pending SIGRTMIN but nothing else.
sigemptyset64(&pending);
ASSERT_EQ(0, sigpending64(&pending)); for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
EXPECT_EQ((i == SIGRTMIN), sigismember64(&pending, i));
}
// Use sigsuspend64 to block everything except SIGRTMIN...
sigset64_t not_SIGRTMIN;
sigfillset64(¬_SIGRTMIN);
sigdelset64(¬_SIGRTMIN, SIGRTMIN);
ASSERT_ERRNO_FAILURE(EINTR, -1, sigsuspend64(¬_SIGRTMIN)); // ...and check that we now receive our pending SIGRTMIN.
ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count);
}
template <typename SigActionT, typename SigSetT> staticvoid TestSigAction(int (sigaction_fn)(int, const SigActionT*, SigActionT*), int (sigaddset_fn)(SigSetT*, int), int sig) { // Both bionic and glibc set SA_RESTORER when talking to the kernel on arm, // arm64, x86, and x86-64. The version of glibc we're using also doesn't // define SA_RESTORER, but luckily it's the same value everywhere. staticconstunsigned sa_restorer = 0x4000000;
// See what's currently set for this signal.
SigActionT original_sa = {};
ASSERT_EQ(0, sigaction_fn(sig, nullptr, &original_sa));
ASSERT_TRUE(original_sa.sa_handler == nullptr);
ASSERT_TRUE(original_sa.sa_sigaction == nullptr);
ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer); #ifdef SA_RESTORER
ASSERT_EQ(bool(original_sa.sa_flags & sa_restorer), bool(original_sa.sa_restorer)); #endif
// Set a traditional sa_handler signal handler. auto no_op_signal_handler = [](int) {};
SigActionT sa = {};
sigaddset_fn(&sa.sa_mask, sig);
sa.sa_flags = SA_ONSTACK;
sa.sa_handler = no_op_signal_handler;
ASSERT_EQ(0, sigaction_fn(sig, &sa, nullptr));
// Check that we can read it back.
sa = {};
ASSERT_EQ(0, sigaction_fn(sig, nullptr, &sa));
ASSERT_TRUE(sa.sa_handler == no_op_signal_handler);
ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK), sa.sa_flags & ~sa_restorer); #ifdef SA_RESTORER
ASSERT_EQ(bool(sa.sa_flags & sa_restorer), bool(sa.sa_restorer)); #endif
// Set a new-style sa_sigaction signal handler. auto no_op_sigaction = [](int, siginfo_t*, void*) {};
sa = {};
sigaddset_fn(&sa.sa_mask, sig);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
sa.sa_sigaction = no_op_sigaction;
ASSERT_EQ(0, sigaction_fn(sig, &sa, nullptr));
// Check that we can read it back.
sa = {};
ASSERT_EQ(0, sigaction_fn(sig, nullptr, &sa));
ASSERT_TRUE(sa.sa_sigaction == no_op_sigaction);
ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); #ifdef SA_RESTORER
ASSERT_EQ(bool(sa.sa_flags & sa_restorer), bool(sa.sa_restorer)); #endif
// Put everything back how it was.
ASSERT_EQ(0, sigaction_fn(sig, &original_sa, nullptr));
}
// glibc filters out signals via sigfillset, not the actual underlying functions.
TEST(signal, sigset_filter) { #ifdefined(__BIONIC__)
TestSignalMaskFunction([]() { for (int i = 1; i <= 64; ++i) {
sigset(i, SIG_HOLD);
}
}); #endif
}
TEST(signal, sighold_filter) { #ifdefined(__BIONIC__)
TestSignalMaskFunction([]() { for (int i = 1; i <= 64; ++i) {
sighold(i);
}
}); #endif
}
#ifdefined(__BIONIC__) && !defined(__riscv) // Not exposed via headers, but the symbols are available if you declare them yourself. extern"C"int sigblock(int); extern"C"int sigsetmask(int); #define HAVE_SIGBLOCK_SIGSETMASK #endif
TEST(signal, sigset_size) { // The setjmp implementations assume that sigset_t can fit in a long. // This is true because the 32-bit ABIs have broken rt signal support, // but the 64-bit ABIs both have a SIGRTMAX defined as 64. #ifdefined(__BIONIC__)
static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long"); #endif
static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals");
}
// sighold(SIGALRM/SIGRTMIN) should add SIGALRM/SIGRTMIN to the signal mask ...
ASSERT_EQ(0, sighold(sig));
ASSERT_EQ(0, sigprocmask(SIG_SETMASK, nullptr, &set));
EXPECT_TRUE(sigismember(&set, sig));
// ... preventing our SIGALRM/SIGRTMIN handler from running ...
raise(sig);
ASSERT_EQ(0, signal_handler_call_count); // ... until sigpause(SIGALRM/SIGRTMIN) temporarily unblocks it.
ASSERT_ERRNO_FAILURE(EINTR, -1, sigpause(sig));
ASSERT_EQ(1, signal_handler_call_count);
// Block SIGALRM so the next sigset(SIGARLM) call will return SIG_HOLD.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &set, nullptr));
TEST(signal, killpg_EINVAL) { // POSIX leaves pgrp <= 1 undefined, but glibc fails with EINVAL for < 0 // and passes 0 through to kill(2).
ASSERT_ERRNO_FAILURE(EINVAL, -1, killpg(-1, SIGKILL));
}
// A regular signal.
ASSERT_EQ(0, sig2str(SIGHUP, str));
ASSERT_STREQ("HUP", str);
// A real-time signal.
ASSERT_EQ(0, sig2str(SIGRTMIN + 4, str));
ASSERT_STREQ("RTMIN+4", str);
ASSERT_EQ(0, sig2str(SIGRTMAX - 4, str));
ASSERT_STREQ("RTMAX-4", str); // Special cases.
ASSERT_EQ(0, sig2str(SIGRTMAX, str));
ASSERT_STREQ("RTMAX", str);
ASSERT_EQ(0, sig2str(SIGRTMIN, str));
ASSERT_STREQ("RTMIN", str); // One of the signals the C library keeps to itself.
ASSERT_EQ(-1, sig2str(32, str)); // __SIGRTMIN
// Errors.
ASSERT_EQ(-1, sig2str(-1, str)); // Too small.
ASSERT_EQ(-1, sig2str(0, str)); // Still too small.
ASSERT_EQ(-1, sig2str(1234, str)); // Too large. #else
GTEST_SKIP() << "our old glibc doesn't have sig2str"; #endif
}
TEST(signal, str2sig) { #ifdefined(__BIONIC__) int sig;
// A regular signal, by number.
sig = -1;
ASSERT_EQ(0, str2sig("9", &sig));
ASSERT_EQ(SIGKILL, sig);
// A regular signal, by name.
sig = -1;
ASSERT_EQ(0, str2sig("HUP", &sig));
ASSERT_EQ(SIGHUP, sig);
// A real-time signal, by number.
sig = -1;
ASSERT_EQ(0, str2sig("64", &sig));
ASSERT_EQ(SIGRTMAX, sig);
// A real-time signal, by name and offset.
sig = -1;
ASSERT_EQ(0, str2sig("RTMAX-4", &sig));
ASSERT_EQ(SIGRTMAX - 4, sig);
sig = -1;
ASSERT_EQ(0, str2sig("RTMIN+4", &sig));
ASSERT_EQ(SIGRTMIN + 4, sig); // Unspecified by POSIX, but we try to be reasonable.
sig = -1;
ASSERT_EQ(0, str2sig("RTMAX-0", &sig));
ASSERT_EQ(SIGRTMAX, sig);
sig = -1;
ASSERT_EQ(0, str2sig("RTMIN+0", &sig));
ASSERT_EQ(SIGRTMIN, sig); // One of the signals the C library keeps to itself, numerically.
ASSERT_EQ(-1, str2sig("32", &sig)); // __SIGRTMIN
// Special cases.
sig = -1;
ASSERT_EQ(0, str2sig("RTMAX", &sig));
ASSERT_EQ(SIGRTMAX, sig);
sig = -1;
ASSERT_EQ(0, str2sig("RTMIN", &sig));
ASSERT_EQ(SIGRTMIN, sig);
// Errors.
ASSERT_EQ(-1, str2sig("SIGHUP", &sig)); // No "SIG" prefix allowed.
ASSERT_EQ(-1, str2sig("-1", &sig)); // Too small.
ASSERT_EQ(-1, str2sig("0", &sig)); // Still too small.
ASSERT_EQ(-1, str2sig("1234", &sig)); // Too large.
ASSERT_EQ(-1, str2sig("RTMAX-666", &sig)); // Offset too small.
ASSERT_EQ(-1, str2sig("RTMIN+666", &sig)); // Offset too large.
ASSERT_EQ(-1, str2sig("RTMAX-+1", &sig)); // Silly.
ASSERT_EQ(-1, str2sig("RTMIN+-1", &sig)); // Silly.
ASSERT_EQ(-1, str2sig("HUPs", &sig)); // Trailing junk.
ASSERT_EQ(-1, str2sig("2b", &sig)); // Trailing junk.
ASSERT_EQ(-1, str2sig("RTMIN+2b", &sig)); // Trailing junk. #else
GTEST_SKIP() << "our old glibc doesn't have str2sig"; #endif
}
TEST(signal, sme_tpidr2_clear) { // When using SME, on entering a signal handler the kernel should clear TPIDR2_EL0, but this was // not always correctly done. This tests checks if the kernel correctly clears it or not. if (!sme_is_enabled()) {
GTEST_SKIP() << "SME is not enabled on device.";
}
TEST(signal, psiginfo) {
android::base::CapturedStderr cap;
siginfo_t si{.si_signo = SIGINT};
psiginfo(&si, "a b c");
ASSERT_EQ(cap.str(), "a b c: Interrupt\n");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.