signal_test.cpp revision c7e9b2331771e5e87c34a8ee3dc6cc41d35b02fe
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <gtest/gtest.h> 18 19#include <errno.h> 20#include <signal.h> 21 22static size_t SIGNAL_MIN() { 23 return 1; // Signals start at 1 (SIGHUP), not 0. 24} 25 26static size_t SIGNAL_MAX() { 27 size_t result = SIGRTMAX; 28 29#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__) 30 // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64. 31 // This means you can't refer to any of the real-time signals. 32 // See http://b/3038348 and http://b/5828899. 33 result = 32; 34#else 35 // Otherwise, C libraries should be perfectly capable of using their largest signal. 36 if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) { 37 abort(); 38 } 39#endif 40 41 return result; 42} 43 44template <typename Fn> 45static void TestSigSet1(Fn fn) { 46 // NULL sigset_t*. 47 sigset_t* set_ptr = NULL; 48 errno = 0; 49 ASSERT_EQ(-1, fn(set_ptr)); 50 ASSERT_EQ(EINVAL, errno); 51 52 // Non-NULL. 53 sigset_t set; 54 errno = 0; 55 ASSERT_EQ(0, fn(&set)); 56 ASSERT_EQ(0, errno); 57} 58 59template <typename Fn> 60static void TestSigSet2(Fn fn) { 61 // NULL sigset_t*. 62 sigset_t* set_ptr = NULL; 63 errno = 0; 64 ASSERT_EQ(-1, fn(set_ptr, SIGSEGV)); 65 ASSERT_EQ(EINVAL, errno); 66 67 sigset_t set; 68 sigemptyset(&set); 69 70 // Bad signal number: too small. 71 errno = 0; 72 ASSERT_EQ(-1, fn(&set, 0)); 73 ASSERT_EQ(EINVAL, errno); 74 75 // Bad signal number: too high. 76 errno = 0; 77 ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1)); 78 ASSERT_EQ(EINVAL, errno); 79 80 // Good signal numbers, low and high ends of range. 81 errno = 0; 82 ASSERT_EQ(0, fn(&set, SIGNAL_MIN())); 83 ASSERT_EQ(0, errno); 84 ASSERT_EQ(0, fn(&set, SIGNAL_MAX())); 85 ASSERT_EQ(0, errno); 86} 87 88class ScopedSignalHandler { 89 public: 90 ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) { 91 sigemptyset(&action_.sa_mask); 92 action_.sa_flags = 0; 93 action_.sa_handler = handler; 94 sigaction(signal_number_, &action_, &old_action_); 95 } 96 97 ~ScopedSignalHandler() { 98 sigaction(signal_number_, &old_action_, NULL); 99 } 100 101 private: 102 struct sigaction action_; 103 struct sigaction old_action_; 104 const int signal_number_; 105}; 106 107TEST(signal, sigismember_invalid) { 108 TestSigSet2(sigismember); 109} 110 111TEST(signal, sigaddset_invalid) { 112 TestSigSet2(sigaddset); 113} 114 115TEST(signal, sigdelset_invalid) { 116 TestSigSet2(sigdelset); 117} 118 119TEST(signal, sigemptyset_invalid) { 120 TestSigSet1(sigemptyset); 121} 122 123TEST(signal, sigfillset_invalid) { 124 TestSigSet1(sigfillset); 125} 126 127TEST(signal, raise_invalid) { 128 errno = 0; 129 ASSERT_EQ(-1, raise(-1)); 130 ASSERT_EQ(EINVAL, errno); 131} 132 133static void raise_in_signal_handler_helper(int signal_number) { 134 ASSERT_EQ(SIGALRM, signal_number); 135 static int count = 0; 136 if (++count == 1) { 137 raise(SIGALRM); 138 } 139} 140 141TEST(signal, raise_in_signal_handler) { 142 ScopedSignalHandler ssh(SIGALRM, raise_in_signal_handler_helper); 143 raise(SIGALRM); 144} 145 146static void HandleSIGALRM(int signal_number) { 147 ASSERT_EQ(SIGALRM, signal_number); 148} 149 150TEST(signal, sigwait) { 151 ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM); 152 153 sigset_t wait_set; 154 sigemptyset(&wait_set); 155 sigaddset(&wait_set, SIGALRM); 156 157 alarm(1); 158 159 int received_signal; 160 errno = 0; 161 ASSERT_EQ(0, sigwait(&wait_set, &received_signal)); 162 ASSERT_EQ(0, errno); 163 ASSERT_EQ(SIGALRM, received_signal); 164} 165 166static int gSigSuspendTestHelperCallCount = 0; 167 168static void SigSuspendTestHelper(int) { 169 ++gSigSuspendTestHelperCallCount; 170} 171 172TEST(signal, sigsuspend_sigpending) { 173 ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper); 174 175 // Block SIGALRM. 176 sigset_t just_SIGALRM; 177 sigemptyset(&just_SIGALRM); 178 sigaddset(&just_SIGALRM, SIGALRM); 179 sigset_t original_set; 180 ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); 181 182 // There should be no pending signals. 183 sigset_t pending; 184 sigemptyset(&pending); 185 ASSERT_EQ(0, sigpending(&pending)); 186 for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { 187 EXPECT_FALSE(sigismember(&pending, i)) << i; 188 } 189 190 // Raise SIGALRM and check our signal handler wasn't called. 191 raise(SIGALRM); 192 ASSERT_EQ(0, gSigSuspendTestHelperCallCount); 193 194 // We should now have a pending SIGALRM but nothing else. 195 sigemptyset(&pending); 196 ASSERT_EQ(0, sigpending(&pending)); 197 for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { 198 EXPECT_EQ((i == SIGALRM), sigismember(&pending, i)); 199 } 200 201 // Use sigsuspend to block everything except SIGALRM... 202 sigset_t not_SIGALRM; 203 sigfillset(¬_SIGALRM); 204 sigdelset(¬_SIGALRM, SIGALRM); 205 ASSERT_EQ(-1, sigsuspend(¬_SIGALRM)); 206 ASSERT_EQ(EINTR, errno); 207 // ...and check that we now receive our pending SIGALRM. 208 ASSERT_EQ(1, gSigSuspendTestHelperCallCount); 209 210 // Restore the original set. 211 assert(0 == sigprocmask(SIG_SETMASK, &original_set, NULL)); 212} 213 214static void EmptySignalHandler(int) {} 215static void EmptySignalAction(int, siginfo_t*, void*) {} 216 217TEST(signal, sigaction) { 218 // See what's currently set for SIGALRM. 219 struct sigaction sa; 220 memset(&sa, 0, sizeof(sa)); 221 ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); 222 ASSERT_TRUE(sa.sa_handler == NULL); 223 ASSERT_TRUE(sa.sa_sigaction == NULL); 224 ASSERT_TRUE(sa.sa_flags == 0); 225 226 // Set a traditional sa_handler signal handler. 227 memset(&sa, 0, sizeof(sa)); 228 sigaddset(&sa.sa_mask, SIGALRM); 229 sa.sa_flags = SA_ONSTACK; 230 sa.sa_handler = EmptySignalHandler; 231 ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL)); 232 233 // Check that we can read it back. 234 memset(&sa, 0, sizeof(sa)); 235 ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); 236 ASSERT_TRUE(sa.sa_handler == EmptySignalHandler); 237 ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); 238 ASSERT_TRUE(sa.sa_flags == SA_ONSTACK); 239 240 // Set a new-style sa_sigaction signal handler. 241 memset(&sa, 0, sizeof(sa)); 242 sigaddset(&sa.sa_mask, SIGALRM); 243 sa.sa_flags = SA_ONSTACK | SA_SIGINFO; 244 sa.sa_sigaction = EmptySignalAction; 245 ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL)); 246 247 // Check that we can read it back. 248 memset(&sa, 0, sizeof(sa)); 249 ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); 250 ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction); 251 ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); 252 ASSERT_TRUE(sa.sa_flags == (SA_ONSTACK | SA_SIGINFO)); 253} 254