diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-02-01 08:54:25 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-02-01 08:54:25 +0000 |
commit | 631d7c2cbfc1cd48720bf111fed463405dbe874c (patch) | |
tree | 92e4fe3ed9dddb34bba5b8598e9b114d99c3884a /tests/signal_test.cpp | |
parent | 9305cdb5c5d4b25915982850388852052a2fb0d0 (diff) | |
parent | a6e115d607264159c9c8c9ba0f460b9478d89a39 (diff) |
Snap for 4579913 from a6e115d607264159c9c8c9ba0f460b9478d89a39 to pi-release
Change-Id: Ibb7ca181f60b205ab68c8e66c5541d0a2c2550bd
Diffstat (limited to 'tests/signal_test.cpp')
-rw-r--r-- | tests/signal_test.cpp | 252 |
1 files changed, 181 insertions, 71 deletions
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index 5cbec883a..ebc079e1d 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -20,57 +20,45 @@ #include <sys/types.h> #include <unistd.h> +#include <thread> + #include <gtest/gtest.h> #include "ScopedSignalHandler.h" -static size_t SIGNAL_MIN() { +static int SIGNAL_MIN() { return 1; // Signals start at 1 (SIGHUP), not 0. } -static size_t SIGNAL_MAX() { - size_t result = SIGRTMAX; - -#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__) - // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64. - // This means you can't refer to any of the real-time signals. - // See http://b/3038348 and http://b/5828899. - result = 32; -#else - // Otherwise, C libraries should be perfectly capable of using their largest signal. - if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) { - abort(); - } -#endif - - return result; +template <typename SigSetT> +static int SIGNAL_MAX(SigSetT* set) { + return sizeof(*set) * 8; } -template <typename Fn> -static void TestSigSet1(Fn fn) { - // NULL sigset_t*. - sigset_t* set_ptr = NULL; +template <typename SigSetT> +static void TestSigSet1(int (fn)(SigSetT*)) { + // NULL sigset_t*/sigset64_t*. + SigSetT* set_ptr = NULL; errno = 0; ASSERT_EQ(-1, fn(set_ptr)); ASSERT_EQ(EINVAL, errno); // Non-NULL. - sigset_t set; + SigSetT set = {}; errno = 0; ASSERT_EQ(0, fn(&set)); ASSERT_EQ(0, errno); } -template <typename Fn> -static void TestSigSet2(Fn fn) { - // NULL sigset_t*. - sigset_t* set_ptr = NULL; +template <typename SigSetT> +static void TestSigSet2(int (fn)(SigSetT*, int)) { + // NULL sigset_t*/sigset64_t*. + SigSetT* set_ptr = NULL; errno = 0; ASSERT_EQ(-1, fn(set_ptr, SIGSEGV)); ASSERT_EQ(EINVAL, errno); - sigset_t set; - sigemptyset(&set); + SigSetT set = {}; // Bad signal number: too small. errno = 0; @@ -79,37 +67,67 @@ static void TestSigSet2(Fn fn) { // Bad signal number: too high. errno = 0; - ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1)); + ASSERT_EQ(-1, fn(&set, SIGNAL_MAX(&set) + 1)); ASSERT_EQ(EINVAL, errno); // Good signal numbers, low and high ends of range. errno = 0; ASSERT_EQ(0, fn(&set, SIGNAL_MIN())); ASSERT_EQ(0, errno); - ASSERT_EQ(0, fn(&set, SIGNAL_MAX())); + ASSERT_EQ(0, fn(&set, SIGNAL_MAX(&set))); ASSERT_EQ(0, errno); } -TEST(signal, sigismember_invalid) { - TestSigSet2(sigismember); -} - TEST(signal, sigaddset_invalid) { TestSigSet2(sigaddset); } +TEST(signal, sigaddset64_invalid) { +#if defined(__BIONIC__) + TestSigSet2(sigaddset64); +#endif +} + TEST(signal, sigdelset_invalid) { TestSigSet2(sigdelset); } +TEST(signal, sigdelset64_invalid) { +#if defined(__BIONIC__) + TestSigSet2(sigdelset64); +#endif +} + TEST(signal, sigemptyset_invalid) { TestSigSet1(sigemptyset); } +TEST(signal, sigemptyset64_invalid) { +#if defined(__BIONIC__) + TestSigSet1(sigemptyset64); +#endif +} + TEST(signal, sigfillset_invalid) { TestSigSet1(sigfillset); } +TEST(signal, sigfillset64_invalid) { +#if defined(__BIONIC__) + TestSigSet1(sigfillset64); +#endif +} + +TEST(signal, sigismember_invalid) { + TestSigSet2(sigismember); +} + +TEST(signal, sigismember64_invalid) { +#if defined(__BIONIC__) + TestSigSet2(sigismember64); +#endif +} + TEST(signal, raise_invalid) { errno = 0; ASSERT_EQ(-1, raise(-1)); @@ -129,12 +147,8 @@ TEST(signal, raise_in_signal_handler) { raise(SIGALRM); } -static void HandleSIGALRM(int signal_number) { - ASSERT_EQ(SIGALRM, signal_number); -} - -TEST(signal, sigwait) { - ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM); +TEST(signal, sigwait_SIGALRM) { + ScopedSignalHandler ssh(SIGALRM, [](int sig) { ASSERT_EQ(SIGALRM, sig); }); sigset_t wait_set; sigemptyset(&wait_set); @@ -149,38 +163,57 @@ TEST(signal, sigwait) { ASSERT_EQ(SIGALRM, received_signal); } -static int g_sigsuspend_test_helper_call_count = 0; +TEST(signal, sigwait64_SIGRTMIN) { + ScopedSignalHandler ssh(SIGRTMIN, [](int sig) { ASSERT_EQ(SIGRTMIN, sig); }); + + sigset64_t wait_set; + sigemptyset64(&wait_set); + sigaddset64(&wait_set, SIGRTMIN); + + pid_t pid = getpid(); + std::thread thread([&pid]() { + usleep(5000); + kill(pid, SIGRTMIN); + }); + + int received_signal; + errno = 0; + ASSERT_EQ(0, sigwait64(&wait_set, &received_signal)); + ASSERT_EQ(0, errno); + ASSERT_EQ(SIGRTMIN, received_signal); -static void SigSuspendTestHelper(int) { - ++g_sigsuspend_test_helper_call_count; + thread.join(); } +static int g_sigsuspend_signal_handler_call_count = 0; + TEST(signal, sigsuspend_sigpending) { + SignalMaskRestorer smr; + // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); - sigset_t original_set; - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); - ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper); + ScopedSignalHandler ssh(SIGALRM, [](int) { ++g_sigsuspend_signal_handler_call_count; }); // There should be no pending signals. sigset_t pending; sigemptyset(&pending); ASSERT_EQ(0, sigpending(&pending)); - for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { + 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_test_helper_call_count); + 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 (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { + for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { EXPECT_EQ((i == SIGALRM), sigismember(&pending, i)); } @@ -191,10 +224,49 @@ TEST(signal, sigsuspend_sigpending) { ASSERT_EQ(-1, sigsuspend(¬_SIGALRM)); ASSERT_EQ(EINTR, errno); // ...and check that we now receive our pending SIGALRM. - ASSERT_EQ(1, g_sigsuspend_test_helper_call_count); + ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count); +} - // Restore the original set. - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +static int g_sigsuspend64_signal_handler_call_count = 0; + +TEST(signal, sigsuspend64_sigpending64) { + SignalMaskRestorer smr; + + // Block SIGRTMIN. + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); + + ScopedSignalHandler ssh(SIGRTMIN, [](int) { ++g_sigsuspend64_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_EQ(-1, sigsuspend64(¬_SIGRTMIN)); + ASSERT_EQ(EINTR, errno); + // ...and check that we now receive our pending SIGRTMIN. + ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count); } static void EmptySignalHandler(int) {} @@ -301,12 +373,13 @@ TEST(signal, sigqueue) { } TEST(signal, sigwaitinfo) { + SignalMaskRestorer smr; + // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); - sigset_t original_set; - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); // Raise SIGALRM. sigval_t sigval; @@ -320,38 +393,75 @@ TEST(signal, sigwaitinfo) { ASSERT_EQ(0, errno); ASSERT_EQ(SIGALRM, info.si_signo); ASSERT_EQ(1, info.si_value.sival_int); +} - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +TEST(signal, sigwaitinfo64_SIGRTMIN) { + SignalMaskRestorer smr; + + // Block SIGRTMIN. + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); + + // Raise SIGRTMIN. + sigval_t sigval; + sigval.sival_int = 1; + ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); + + // Get pending SIGRTMIN. + siginfo_t info; + errno = 0; + ASSERT_EQ(SIGRTMIN, sigwaitinfo64(&just_SIGRTMIN, &info)); + ASSERT_EQ(0, errno); + ASSERT_EQ(SIGRTMIN, info.si_signo); + ASSERT_EQ(1, info.si_value.sival_int); } TEST(signal, sigtimedwait) { + SignalMaskRestorer smr; + // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); - sigset_t original_set; - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); // Raise SIGALRM. - sigval_t sigval; - sigval.sival_int = 1; + sigval_t sigval = { .sival_int = 1 }; ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); // Get pending SIGALRM. siginfo_t info; - struct timespec timeout; - timeout.tv_sec = 2; - timeout.tv_nsec = 0; + timespec timeout = { .tv_sec = 2, .tv_nsec = 0 }; errno = 0; ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout)); ASSERT_EQ(0, errno); +} - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +TEST(signal, sigtimedwait64_SIGRTMIN) { + SignalMaskRestorer smr; + + // Block SIGRTMIN. + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); + + // Raise SIGALRM. + sigval_t sigval = { .sival_int = 1 }; + ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); + + // Get pending SIGALRM. + siginfo_t info; + timespec timeout = { .tv_sec = 2, .tv_nsec = 0 }; + errno = 0; + ASSERT_EQ(SIGRTMIN, sigtimedwait64(&just_SIGRTMIN, &info, &timeout)); + ASSERT_EQ(0, errno); } static int64_t NanoTime() { - struct timespec t; - t.tv_sec = t.tv_nsec = 0; + timespec t; clock_gettime(CLOCK_MONOTONIC, &t); return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec; } @@ -367,9 +477,7 @@ TEST(signal, sigtimedwait_timeout) { // Wait timeout. int64_t start_time = NanoTime(); siginfo_t info; - struct timespec timeout; - timeout.tv_sec = 0; - timeout.tv_nsec = 1000000; + timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 }; errno = 0; ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout)); ASSERT_EQ(EAGAIN, errno); @@ -411,17 +519,19 @@ TEST(signal, rt_tgsigqueueinfo) { << sent.si_code << ", received " << received.si_code << error_msg; } +#endif -#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) TEST(signal, sigset_size) { // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64 // both have a SIGRTMAX defined as 64. +#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) +#if defined(__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"); #endif +} TEST(signal, sigignore_EINVAL) { errno = 0; |