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 <errno.h> 18#include <signal.h> 19#include <sys/syscall.h> 20#include <sys/types.h> 21#include <unistd.h> 22 23#include <gtest/gtest.h> 24 25#include "ScopedSignalHandler.h" 26 27static size_t SIGNAL_MIN() { 28 return 1; // Signals start at 1 (SIGHUP), not 0. 29} 30 31static size_t SIGNAL_MAX() { 32 size_t result = SIGRTMAX; 33 34#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__) 35 // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64. 36 // This means you can't refer to any of the real-time signals. 37 // See http://b/3038348 and http://b/5828899. 38 result = 32; 39#else 40 // Otherwise, C libraries should be perfectly capable of using their largest signal. 41 if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) { 42 abort(); 43 } 44#endif 45 46 return result; 47} 48 49template <typename Fn> 50static void TestSigSet1(Fn fn) { 51 // NULL sigset_t*. 52 sigset_t* set_ptr = NULL; 53 errno = 0; 54 ASSERT_EQ(-1, fn(set_ptr)); 55 ASSERT_EQ(EINVAL, errno); 56 57 // Non-NULL. 58 sigset_t set; 59 errno = 0; 60 ASSERT_EQ(0, fn(&set)); 61 ASSERT_EQ(0, errno); 62} 63 64template <typename Fn> 65static void TestSigSet2(Fn fn) { 66 // NULL sigset_t*. 67 sigset_t* set_ptr = NULL; 68 errno = 0; 69 ASSERT_EQ(-1, fn(set_ptr, SIGSEGV)); 70 ASSERT_EQ(EINVAL, errno); 71 72 sigset_t set; 73 sigemptyset(&set); 74 75 // Bad signal number: too small. 76 errno = 0; 77 ASSERT_EQ(-1, fn(&set, 0)); 78 ASSERT_EQ(EINVAL, errno); 79 80 // Bad signal number: too high. 81 errno = 0; 82 ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1)); 83 ASSERT_EQ(EINVAL, errno); 84 85 // Good signal numbers, low and high ends of range. 86 errno = 0; 87 ASSERT_EQ(0, fn(&set, SIGNAL_MIN())); 88 ASSERT_EQ(0, errno); 89 ASSERT_EQ(0, fn(&set, SIGNAL_MAX())); 90 ASSERT_EQ(0, errno); 91} 92 93TEST(signal, sigismember_invalid) { 94 TestSigSet2(sigismember); 95} 96 97TEST(signal, sigaddset_invalid) { 98 TestSigSet2(sigaddset); 99} 100 101TEST(signal, sigdelset_invalid) { 102 TestSigSet2(sigdelset); 103} 104 105TEST(signal, sigemptyset_invalid) { 106 TestSigSet1(sigemptyset); 107} 108 109TEST(signal, sigfillset_invalid) { 110 TestSigSet1(sigfillset); 111} 112 113TEST(signal, raise_invalid) { 114 errno = 0; 115 ASSERT_EQ(-1, raise(-1)); 116 ASSERT_EQ(EINVAL, errno); 117} 118 119static void raise_in_signal_handler_helper(int signal_number) { 120 ASSERT_EQ(SIGALRM, signal_number); 121 static int count = 0; 122 if (++count == 1) { 123 raise(SIGALRM); 124 } 125} 126 127TEST(signal, raise_in_signal_handler) { 128 ScopedSignalHandler ssh(SIGALRM, raise_in_signal_handler_helper); 129 raise(SIGALRM); 130} 131 132static void HandleSIGALRM(int signal_number) { 133 ASSERT_EQ(SIGALRM, signal_number); 134} 135 136TEST(signal, sigwait) { 137 ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM); 138 139 sigset_t wait_set; 140 sigemptyset(&wait_set); 141 sigaddset(&wait_set, SIGALRM); 142 143 alarm(1); 144 145 int received_signal; 146 errno = 0; 147 ASSERT_EQ(0, sigwait(&wait_set, &received_signal)); 148 ASSERT_EQ(0, errno); 149 ASSERT_EQ(SIGALRM, received_signal); 150} 151 152static int g_sigsuspend_test_helper_call_count = 0; 153 154static void SigSuspendTestHelper(int) { 155 ++g_sigsuspend_test_helper_call_count; 156} 157 158TEST(signal, sigsuspend_sigpending) { 159 // Block SIGALRM. 160 sigset_t just_SIGALRM; 161 sigemptyset(&just_SIGALRM); 162 sigaddset(&just_SIGALRM, SIGALRM); 163 sigset_t original_set; 164 ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); 165 166 ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper); 167 168 // There should be no pending signals. 169 sigset_t pending; 170 sigemptyset(&pending); 171 ASSERT_EQ(0, sigpending(&pending)); 172 for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { 173 EXPECT_FALSE(sigismember(&pending, i)) << i; 174 } 175 176 // Raise SIGALRM and check our signal handler wasn't called. 177 raise(SIGALRM); 178 ASSERT_EQ(0, g_sigsuspend_test_helper_call_count); 179 180 // We should now have a pending SIGALRM but nothing else. 181 sigemptyset(&pending); 182 ASSERT_EQ(0, sigpending(&pending)); 183 for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { 184 EXPECT_EQ((i == SIGALRM), sigismember(&pending, i)); 185 } 186 187 // Use sigsuspend to block everything except SIGALRM... 188 sigset_t not_SIGALRM; 189 sigfillset(¬_SIGALRM); 190 sigdelset(¬_SIGALRM, SIGALRM); 191 ASSERT_EQ(-1, sigsuspend(¬_SIGALRM)); 192 ASSERT_EQ(EINTR, errno); 193 // ...and check that we now receive our pending SIGALRM. 194 ASSERT_EQ(1, g_sigsuspend_test_helper_call_count); 195 196 // Restore the original set. 197 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); 198} 199 200static void EmptySignalHandler(int) {} 201static void EmptySignalAction(int, siginfo_t*, void*) {} 202 203TEST(signal, sigaction) { 204 // Both bionic and glibc set SA_RESTORER when talking to the kernel on arm, 205 // arm64, x86, and x86-64. The version of glibc we're using also doesn't 206 // define SA_RESTORER, but luckily it's the same value everywhere, and mips 207 // doesn't use the bit for anything. 208 static const unsigned sa_restorer = 0x4000000; 209 210 // See what's currently set for SIGALRM. 211 struct sigaction original_sa; 212 memset(&original_sa, 0, sizeof(original_sa)); 213 ASSERT_EQ(0, sigaction(SIGALRM, NULL, &original_sa)); 214 ASSERT_TRUE(original_sa.sa_handler == NULL); 215 ASSERT_TRUE(original_sa.sa_sigaction == NULL); 216 ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer); 217 218 // Set a traditional sa_handler signal handler. 219 struct sigaction sa; 220 memset(&sa, 0, sizeof(sa)); 221 sigaddset(&sa.sa_mask, SIGALRM); 222 sa.sa_flags = SA_ONSTACK; 223 sa.sa_handler = EmptySignalHandler; 224 ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL)); 225 226 // Check that we can read it back. 227 memset(&sa, 0, sizeof(sa)); 228 ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); 229 ASSERT_TRUE(sa.sa_handler == EmptySignalHandler); 230 ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); 231 ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK), sa.sa_flags & ~sa_restorer); 232 233 // Set a new-style sa_sigaction signal handler. 234 memset(&sa, 0, sizeof(sa)); 235 sigaddset(&sa.sa_mask, SIGALRM); 236 sa.sa_flags = SA_ONSTACK | SA_SIGINFO; 237 sa.sa_sigaction = EmptySignalAction; 238 ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL)); 239 240 // Check that we can read it back. 241 memset(&sa, 0, sizeof(sa)); 242 ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); 243 ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction); 244 ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); 245 ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); 246 247 // Put everything back how it was. 248 ASSERT_EQ(0, sigaction(SIGALRM, &original_sa, NULL)); 249} 250 251TEST(signal, sys_signame) { 252#if defined(__BIONIC__) 253 ASSERT_TRUE(sys_signame[0] == NULL); 254 ASSERT_STREQ("HUP", sys_signame[SIGHUP]); 255#else 256 GTEST_LOG_(INFO) << "This test does nothing.\n"; 257#endif 258} 259 260TEST(signal, sys_siglist) { 261 ASSERT_TRUE(sys_siglist[0] == NULL); 262 ASSERT_STREQ("Hangup", sys_siglist[SIGHUP]); 263} 264 265TEST(signal, limits) { 266 // This comes from the kernel. 267 ASSERT_EQ(32, __SIGRTMIN); 268 269 // We reserve a non-zero number at the bottom for ourselves. 270 ASSERT_GT(SIGRTMIN, __SIGRTMIN); 271 272 // MIPS has more signals than everyone else. 273#if defined(__mips__) 274 ASSERT_EQ(128, __SIGRTMAX); 275#else 276 ASSERT_EQ(64, __SIGRTMAX); 277#endif 278 279 // We don't currently reserve any at the top. 280 ASSERT_EQ(SIGRTMAX, __SIGRTMAX); 281} 282 283static int g_sigqueue_signal_handler_call_count = 0; 284 285static void SigqueueSignalHandler(int signum, siginfo_t* info, void*) { 286 ASSERT_EQ(SIGALRM, signum); 287 ASSERT_EQ(SIGALRM, info->si_signo); 288 ASSERT_EQ(SI_QUEUE, info->si_code); 289 ASSERT_EQ(1, info->si_value.sival_int); 290 ++g_sigqueue_signal_handler_call_count; 291} 292 293TEST(signal, sigqueue) { 294 ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); 295 sigval_t sigval; 296 sigval.sival_int = 1; 297 errno = 0; 298 ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); 299 ASSERT_EQ(0, errno); 300 ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); 301} 302 303TEST(signal, sigwaitinfo) { 304 // Block SIGALRM. 305 sigset_t just_SIGALRM; 306 sigemptyset(&just_SIGALRM); 307 sigaddset(&just_SIGALRM, SIGALRM); 308 sigset_t original_set; 309 ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); 310 311 // Raise SIGALRM. 312 sigval_t sigval; 313 sigval.sival_int = 1; 314 ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); 315 316 // Get pending SIGALRM. 317 siginfo_t info; 318 errno = 0; 319 ASSERT_EQ(SIGALRM, sigwaitinfo(&just_SIGALRM, &info)); 320 ASSERT_EQ(0, errno); 321 ASSERT_EQ(SIGALRM, info.si_signo); 322 ASSERT_EQ(1, info.si_value.sival_int); 323 324 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); 325} 326 327TEST(signal, sigtimedwait) { 328 // Block SIGALRM. 329 sigset_t just_SIGALRM; 330 sigemptyset(&just_SIGALRM); 331 sigaddset(&just_SIGALRM, SIGALRM); 332 sigset_t original_set; 333 ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); 334 335 // Raise SIGALRM. 336 sigval_t sigval; 337 sigval.sival_int = 1; 338 ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); 339 340 // Get pending SIGALRM. 341 siginfo_t info; 342 struct timespec timeout; 343 timeout.tv_sec = 2; 344 timeout.tv_nsec = 0; 345 errno = 0; 346 ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout)); 347 ASSERT_EQ(0, errno); 348 349 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); 350} 351 352static int64_t NanoTime() { 353 struct timespec t; 354 t.tv_sec = t.tv_nsec = 0; 355 clock_gettime(CLOCK_MONOTONIC, &t); 356 return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec; 357} 358 359TEST(signal, sigtimedwait_timeout) { 360 // Block SIGALRM. 361 sigset_t just_SIGALRM; 362 sigemptyset(&just_SIGALRM); 363 sigaddset(&just_SIGALRM, SIGALRM); 364 sigset_t original_set; 365 ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); 366 367 // Wait timeout. 368 int64_t start_time = NanoTime(); 369 siginfo_t info; 370 struct timespec timeout; 371 timeout.tv_sec = 0; 372 timeout.tv_nsec = 1000000; 373 errno = 0; 374 ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout)); 375 ASSERT_EQ(EAGAIN, errno); 376 ASSERT_GE(NanoTime() - start_time, 1000000); 377 378 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); 379} 380 381#if defined(__BIONIC__) 382TEST(signal, rt_tgsigqueueinfo) { 383 // Test whether rt_tgsigqueueinfo allows sending arbitrary si_code values to self. 384 // If this fails, your kernel needs commit 66dd34a to be backported. 385 static constexpr char error_msg[] = 386 "\nPlease ensure that the following kernel patch has been applied:\n" 387 "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921\n"; 388 static siginfo received; 389 390 struct sigaction handler; 391 memset(&handler, 0, sizeof(handler)); 392 handler.sa_sigaction = [](int, siginfo_t* siginfo, void*) { received = *siginfo; }; 393 handler.sa_flags = SA_SIGINFO; 394 395 ASSERT_EQ(0, sigaction(SIGUSR1, &handler, nullptr)); 396 397 siginfo sent; 398 memset(&sent, 0, sizeof(sent)); 399 400 sent.si_code = SI_TKILL; 401 ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent)) 402 << "rt_tgsigqueueinfo failed: " << strerror(errno) << error_msg; 403 ASSERT_EQ(sent.si_code, received.si_code) << "rt_tgsigqueueinfo modified si_code, expected " 404 << sent.si_code << ", received " << received.si_code 405 << error_msg; 406 407 sent.si_code = SI_USER; 408 ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent)) 409 << "rt_tgsigqueueinfo failed: " << strerror(errno) << error_msg; 410 ASSERT_EQ(sent.si_code, received.si_code) << "rt_tgsigqueueinfo modified si_code, expected " 411 << sent.si_code << ", received " << received.si_code 412 << error_msg; 413} 414 415#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) 416TEST(signal, sigset_size) { 417 // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a 418 // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64 419 // both have a SIGRTMAX defined as 64. 420 static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long"); 421} 422 423#endif 424#endif 425