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