| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 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 |  | 
| Josh Gao | 61cf3f3 | 2016-03-08 15:27:15 -0800 | [diff] [blame] | 17 | #include <errno.h> | 
| Elliott Hughes | afe58ad | 2014-09-04 13:54:42 -0700 | [diff] [blame] | 18 | #include <signal.h> | 
| Colin Cross | 4c5595c | 2021-08-16 15:51:59 -0700 | [diff] [blame] | 19 | #include <sys/cdefs.h> | 
| Josh Gao | 61cf3f3 | 2016-03-08 15:27:15 -0800 | [diff] [blame] | 20 | #include <sys/syscall.h> | 
 | 21 | #include <sys/types.h> | 
 | 22 | #include <unistd.h> | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 23 |  | 
| Elliott Hughes | ca3f8e4 | 2019-10-28 15:59:38 -0700 | [diff] [blame] | 24 | #include <chrono> | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 25 | #include <thread> | 
 | 26 |  | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 27 | #include <android-base/macros.h> | 
| Evgeny Eltsin | 4d9264c | 2019-12-17 14:17:07 +0100 | [diff] [blame] | 28 | #include <android-base/threads.h> | 
 | 29 |  | 
| Elliott Hughes | afe58ad | 2014-09-04 13:54:42 -0700 | [diff] [blame] | 30 | #include <gtest/gtest.h> | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 31 |  | 
| Elliott Hughes | 71ba589 | 2018-02-07 12:44:45 -0800 | [diff] [blame] | 32 | #include "SignalUtils.h" | 
| Evgeny Eltsin | 4d9264c | 2019-12-17 14:17:07 +0100 | [diff] [blame] | 33 | #include "utils.h" | 
| Christopher Ferris | 1361313 | 2013-10-28 15:24:04 -0700 | [diff] [blame] | 34 |  | 
| Elliott Hughes | ca3f8e4 | 2019-10-28 15:59:38 -0700 | [diff] [blame] | 35 | using namespace std::chrono_literals; | 
 | 36 |  | 
| Colin Cross | 23b986c | 2022-10-19 15:03:59 -0700 | [diff] [blame] | 37 | #if defined(ANDROID_HOST_MUSL) | 
 | 38 | // Musl doesn't export __SIGRTMIN and __SIGRTMAX, #define | 
 | 39 | // them here. | 
 | 40 | #define __SIGRTMIN 32 | 
 | 41 | #define __SIGRTMAX 64 | 
 | 42 | #endif | 
 | 43 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 44 | static int SIGNAL_MIN() { | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 45 |   return 1; // Signals start at 1 (SIGHUP), not 0. | 
 | 46 | } | 
 | 47 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 48 | template <typename SigSetT> | 
 | 49 | static int SIGNAL_MAX(SigSetT* set) { | 
 | 50 |   return sizeof(*set) * 8; | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 51 | } | 
 | 52 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 53 | template <typename SigSetT> | 
 | 54 | static void TestSigSet1(int (fn)(SigSetT*)) { | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 55 |   // nullptr sigset_t*/sigset64_t*. | 
 | 56 |   SigSetT* set_ptr = nullptr; | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 57 |   errno = 0; | 
 | 58 |   ASSERT_EQ(-1, fn(set_ptr)); | 
 | 59 |   ASSERT_EQ(EINVAL, errno); | 
 | 60 |  | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 61 |   // Non-nullptr. | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 62 |   SigSetT set = {}; | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 63 |   errno = 0; | 
 | 64 |   ASSERT_EQ(0, fn(&set)); | 
 | 65 |   ASSERT_EQ(0, errno); | 
 | 66 | } | 
 | 67 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 68 | template <typename SigSetT> | 
 | 69 | static void TestSigSet2(int (fn)(SigSetT*, int)) { | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 70 |   // nullptr sigset_t*/sigset64_t*. | 
 | 71 |   SigSetT* set_ptr = nullptr; | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 72 |   errno = 0; | 
 | 73 |   ASSERT_EQ(-1, fn(set_ptr, SIGSEGV)); | 
 | 74 |   ASSERT_EQ(EINVAL, errno); | 
 | 75 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 76 |   SigSetT set = {}; | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 77 |  | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 78 |   // Bad signal number: too small. | 
 | 79 |   errno = 0; | 
 | 80 |   ASSERT_EQ(-1, fn(&set, 0)); | 
 | 81 |   ASSERT_EQ(EINVAL, errno); | 
 | 82 |  | 
 | 83 |   // Bad signal number: too high. | 
 | 84 |   errno = 0; | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 85 |   ASSERT_EQ(-1, fn(&set, SIGNAL_MAX(&set) + 1)); | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 86 |   ASSERT_EQ(EINVAL, errno); | 
 | 87 |  | 
 | 88 |   // Good signal numbers, low and high ends of range. | 
 | 89 |   errno = 0; | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 90 |   ASSERT_EQ(0, fn(&set, SIGNAL_MIN())); | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 91 |   ASSERT_EQ(0, errno); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 92 |   ASSERT_EQ(0, fn(&set, SIGNAL_MAX(&set))); | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 93 |   ASSERT_EQ(0, errno); | 
 | 94 | } | 
 | 95 |  | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 96 | TEST(signal, sigaddset_invalid) { | 
 | 97 |   TestSigSet2(sigaddset); | 
 | 98 | } | 
 | 99 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 100 | TEST(signal, sigaddset64_invalid) { | 
 | 101 | #if defined(__BIONIC__) | 
 | 102 |   TestSigSet2(sigaddset64); | 
 | 103 | #endif | 
 | 104 | } | 
 | 105 |  | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 106 | TEST(signal, sigdelset_invalid) { | 
 | 107 |   TestSigSet2(sigdelset); | 
 | 108 | } | 
 | 109 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 110 | TEST(signal, sigdelset64_invalid) { | 
 | 111 | #if defined(__BIONIC__) | 
 | 112 |   TestSigSet2(sigdelset64); | 
 | 113 | #endif | 
 | 114 | } | 
 | 115 |  | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 116 | TEST(signal, sigemptyset_invalid) { | 
 | 117 |   TestSigSet1(sigemptyset); | 
 | 118 | } | 
 | 119 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 120 | TEST(signal, sigemptyset64_invalid) { | 
 | 121 | #if defined(__BIONIC__) | 
 | 122 |   TestSigSet1(sigemptyset64); | 
 | 123 | #endif | 
 | 124 | } | 
 | 125 |  | 
| Elliott Hughes | da73f65 | 2012-11-30 16:40:55 -0800 | [diff] [blame] | 126 | TEST(signal, sigfillset_invalid) { | 
 | 127 |   TestSigSet1(sigfillset); | 
 | 128 | } | 
| Chris Dearman | d8a5a6f | 2012-12-07 18:41:10 -0800 | [diff] [blame] | 129 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 130 | TEST(signal, sigfillset64_invalid) { | 
 | 131 | #if defined(__BIONIC__) | 
 | 132 |   TestSigSet1(sigfillset64); | 
 | 133 | #endif | 
 | 134 | } | 
 | 135 |  | 
 | 136 | TEST(signal, sigismember_invalid) { | 
 | 137 |   TestSigSet2(sigismember); | 
 | 138 | } | 
 | 139 |  | 
 | 140 | TEST(signal, sigismember64_invalid) { | 
 | 141 | #if defined(__BIONIC__) | 
 | 142 |   TestSigSet2(sigismember64); | 
 | 143 | #endif | 
 | 144 | } | 
 | 145 |  | 
| Chris Dearman | d8a5a6f | 2012-12-07 18:41:10 -0800 | [diff] [blame] | 146 | TEST(signal, raise_invalid) { | 
 | 147 |   errno = 0; | 
 | 148 |   ASSERT_EQ(-1, raise(-1)); | 
 | 149 |   ASSERT_EQ(EINVAL, errno); | 
 | 150 | } | 
| Elliott Hughes | c5d028f | 2013-01-10 14:42:14 -0800 | [diff] [blame] | 151 |  | 
| Elliott Hughes | fae89fc | 2013-02-21 11:22:23 -0800 | [diff] [blame] | 152 | static void raise_in_signal_handler_helper(int signal_number) { | 
 | 153 |   ASSERT_EQ(SIGALRM, signal_number); | 
 | 154 |   static int count = 0; | 
 | 155 |   if (++count == 1) { | 
 | 156 |     raise(SIGALRM); | 
 | 157 |   } | 
 | 158 | } | 
 | 159 |  | 
 | 160 | TEST(signal, raise_in_signal_handler) { | 
 | 161 |   ScopedSignalHandler ssh(SIGALRM, raise_in_signal_handler_helper); | 
 | 162 |   raise(SIGALRM); | 
 | 163 | } | 
 | 164 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 165 | static int g_sigsuspend_signal_handler_call_count = 0; | 
 | 166 |  | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 167 | TEST(signal, sigsuspend_sigpending) { | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 168 |   SignalMaskRestorer smr; | 
 | 169 |  | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 170 |   // Block SIGALRM. | 
 | 171 |   sigset_t just_SIGALRM; | 
 | 172 |   sigemptyset(&just_SIGALRM); | 
 | 173 |   sigaddset(&just_SIGALRM, SIGALRM); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 174 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 175 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 176 |   ScopedSignalHandler ssh(SIGALRM, [](int) { ++g_sigsuspend_signal_handler_call_count; }); | 
| Elliott Hughes | 1195207 | 2013-10-24 15:15:14 -0700 | [diff] [blame] | 177 |  | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 178 |   // There should be no pending signals. | 
 | 179 |   sigset_t pending; | 
 | 180 |   sigemptyset(&pending); | 
 | 181 |   ASSERT_EQ(0, sigpending(&pending)); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 182 |   for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 183 |     EXPECT_FALSE(sigismember(&pending, i)) << i; | 
 | 184 |   } | 
 | 185 |  | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 186 |   // Raise SIGALRM and check our signal handler wasn't called. | 
 | 187 |   raise(SIGALRM); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 188 |   ASSERT_EQ(0, g_sigsuspend_signal_handler_call_count); | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 189 |  | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 190 |   // We should now have a pending SIGALRM but nothing else. | 
 | 191 |   sigemptyset(&pending); | 
 | 192 |   ASSERT_EQ(0, sigpending(&pending)); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 193 |   for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { | 
| Elliott Hughes | 40d105c | 2013-10-16 12:53:58 -0700 | [diff] [blame] | 194 |     EXPECT_EQ((i == SIGALRM), sigismember(&pending, i)); | 
 | 195 |   } | 
 | 196 |  | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 197 |   // Use sigsuspend to block everything except SIGALRM... | 
 | 198 |   sigset_t not_SIGALRM; | 
 | 199 |   sigfillset(¬_SIGALRM); | 
 | 200 |   sigdelset(¬_SIGALRM, SIGALRM); | 
 | 201 |   ASSERT_EQ(-1, sigsuspend(¬_SIGALRM)); | 
 | 202 |   ASSERT_EQ(EINTR, errno); | 
 | 203 |   // ...and check that we now receive our pending SIGALRM. | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 204 |   ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count); | 
 | 205 | } | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 206 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 207 | static int g_sigsuspend64_signal_handler_call_count = 0; | 
 | 208 |  | 
 | 209 | TEST(signal, sigsuspend64_sigpending64) { | 
 | 210 |   SignalMaskRestorer smr; | 
 | 211 |  | 
 | 212 |   // Block SIGRTMIN. | 
 | 213 |   sigset64_t just_SIGRTMIN; | 
 | 214 |   sigemptyset64(&just_SIGRTMIN); | 
 | 215 |   sigaddset64(&just_SIGRTMIN, SIGRTMIN); | 
 | 216 |   ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); | 
 | 217 |  | 
 | 218 |   ScopedSignalHandler ssh(SIGRTMIN, [](int) { ++g_sigsuspend64_signal_handler_call_count; }); | 
 | 219 |  | 
 | 220 |   // There should be no pending signals. | 
 | 221 |   sigset64_t pending; | 
 | 222 |   sigemptyset64(&pending); | 
 | 223 |   ASSERT_EQ(0, sigpending64(&pending)); | 
 | 224 |   for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { | 
 | 225 |     EXPECT_FALSE(sigismember64(&pending, i)) << i; | 
 | 226 |   } | 
 | 227 |  | 
 | 228 |   // Raise SIGRTMIN and check our signal handler wasn't called. | 
 | 229 |   raise(SIGRTMIN); | 
 | 230 |   ASSERT_EQ(0, g_sigsuspend64_signal_handler_call_count); | 
 | 231 |  | 
 | 232 |   // We should now have a pending SIGRTMIN but nothing else. | 
 | 233 |   sigemptyset64(&pending); | 
 | 234 |   ASSERT_EQ(0, sigpending64(&pending)); | 
 | 235 |   for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { | 
 | 236 |     EXPECT_EQ((i == SIGRTMIN), sigismember64(&pending, i)); | 
 | 237 |   } | 
 | 238 |  | 
 | 239 |   // Use sigsuspend64 to block everything except SIGRTMIN... | 
 | 240 |   sigset64_t not_SIGRTMIN; | 
 | 241 |   sigfillset64(¬_SIGRTMIN); | 
 | 242 |   sigdelset64(¬_SIGRTMIN, SIGRTMIN); | 
 | 243 |   ASSERT_EQ(-1, sigsuspend64(¬_SIGRTMIN)); | 
 | 244 |   ASSERT_EQ(EINTR, errno); | 
 | 245 |   // ...and check that we now receive our pending SIGRTMIN. | 
 | 246 |   ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count); | 
| Elliott Hughes | 1f5af92 | 2013-10-15 18:01:56 -0700 | [diff] [blame] | 247 | } | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 248 |  | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 249 | template <typename SigActionT, typename SigSetT> | 
 | 250 | static void TestSigAction(int (sigaction_fn)(int, const SigActionT*, SigActionT*), | 
 | 251 |                           int (sigaddset_fn)(SigSetT*, int), | 
 | 252 |                           int sig) { | 
| Elliott Hughes | afe58ad | 2014-09-04 13:54:42 -0700 | [diff] [blame] | 253 |   // Both bionic and glibc set SA_RESTORER when talking to the kernel on arm, | 
 | 254 |   // arm64, x86, and x86-64. The version of glibc we're using also doesn't | 
| Elliott Hughes | 6a65ccd | 2020-02-13 09:48:14 -0800 | [diff] [blame] | 255 |   // define SA_RESTORER, but luckily it's the same value everywhere. | 
| Elliott Hughes | aa13e83 | 2014-09-04 15:43:10 -0700 | [diff] [blame] | 256 |   static const unsigned sa_restorer = 0x4000000; | 
| Elliott Hughes | afe58ad | 2014-09-04 13:54:42 -0700 | [diff] [blame] | 257 |  | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 258 |   // See what's currently set for this signal. | 
 | 259 |   SigActionT original_sa = {}; | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 260 |   ASSERT_EQ(0, sigaction_fn(sig, nullptr, &original_sa)); | 
 | 261 |   ASSERT_TRUE(original_sa.sa_handler == nullptr); | 
 | 262 |   ASSERT_TRUE(original_sa.sa_sigaction == nullptr); | 
| Elliott Hughes | aa13e83 | 2014-09-04 15:43:10 -0700 | [diff] [blame] | 263 |   ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer); | 
| Goran Jakovljevic | 3796669 | 2018-02-12 09:03:10 +0100 | [diff] [blame] | 264 | #ifdef SA_RESTORER | 
| Evgeny Eltsin | 11f6076 | 2018-02-05 13:33:35 +0100 | [diff] [blame] | 265 |   ASSERT_EQ(bool(original_sa.sa_flags & sa_restorer), bool(original_sa.sa_restorer)); | 
| Goran Jakovljevic | 3796669 | 2018-02-12 09:03:10 +0100 | [diff] [blame] | 266 | #endif | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 267 |  | 
 | 268 |   // Set a traditional sa_handler signal handler. | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 269 |   auto no_op_signal_handler = [](int) {}; | 
 | 270 |   SigActionT sa = {}; | 
 | 271 |   sigaddset_fn(&sa.sa_mask, sig); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 272 |   sa.sa_flags = SA_ONSTACK; | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 273 |   sa.sa_handler = no_op_signal_handler; | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 274 |   ASSERT_EQ(0, sigaction_fn(sig, &sa, nullptr)); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 275 |  | 
 | 276 |   // Check that we can read it back. | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 277 |   sa = {}; | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 278 |   ASSERT_EQ(0, sigaction_fn(sig, nullptr, &sa)); | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 279 |   ASSERT_TRUE(sa.sa_handler == no_op_signal_handler); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 280 |   ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); | 
| Elliott Hughes | aa13e83 | 2014-09-04 15:43:10 -0700 | [diff] [blame] | 281 |   ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK), sa.sa_flags & ~sa_restorer); | 
| Goran Jakovljevic | 3796669 | 2018-02-12 09:03:10 +0100 | [diff] [blame] | 282 | #ifdef SA_RESTORER | 
| Evgeny Eltsin | 11f6076 | 2018-02-05 13:33:35 +0100 | [diff] [blame] | 283 |   ASSERT_EQ(bool(sa.sa_flags & sa_restorer), bool(sa.sa_restorer)); | 
| Goran Jakovljevic | 3796669 | 2018-02-12 09:03:10 +0100 | [diff] [blame] | 284 | #endif | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 285 |  | 
 | 286 |   // Set a new-style sa_sigaction signal handler. | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 287 |   auto no_op_sigaction = [](int, siginfo_t*, void*) {}; | 
 | 288 |   sa = {}; | 
 | 289 |   sigaddset_fn(&sa.sa_mask, sig); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 290 |   sa.sa_flags = SA_ONSTACK | SA_SIGINFO; | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 291 |   sa.sa_sigaction = no_op_sigaction; | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 292 |   ASSERT_EQ(0, sigaction_fn(sig, &sa, nullptr)); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 293 |  | 
 | 294 |   // Check that we can read it back. | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 295 |   sa = {}; | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 296 |   ASSERT_EQ(0, sigaction_fn(sig, nullptr, &sa)); | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 297 |   ASSERT_TRUE(sa.sa_sigaction == no_op_sigaction); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 298 |   ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); | 
| Elliott Hughes | aa13e83 | 2014-09-04 15:43:10 -0700 | [diff] [blame] | 299 |   ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); | 
| Goran Jakovljevic | 3796669 | 2018-02-12 09:03:10 +0100 | [diff] [blame] | 300 | #ifdef SA_RESTORER | 
| Evgeny Eltsin | 11f6076 | 2018-02-05 13:33:35 +0100 | [diff] [blame] | 301 |   ASSERT_EQ(bool(sa.sa_flags & sa_restorer), bool(sa.sa_restorer)); | 
| Goran Jakovljevic | 3796669 | 2018-02-12 09:03:10 +0100 | [diff] [blame] | 302 | #endif | 
| Elliott Hughes | 1195207 | 2013-10-24 15:15:14 -0700 | [diff] [blame] | 303 |  | 
 | 304 |   // Put everything back how it was. | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 305 |   ASSERT_EQ(0, sigaction_fn(sig, &original_sa, nullptr)); | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 306 | } | 
 | 307 |  | 
 | 308 | TEST(signal, sigaction) { | 
 | 309 |   TestSigAction(sigaction, sigaddset, SIGALRM); | 
 | 310 | } | 
 | 311 |  | 
 | 312 | TEST(signal, sigaction64_SIGRTMIN) { | 
 | 313 |   TestSigAction(sigaction64, sigaddset64, SIGRTMIN); | 
| Elliott Hughes | c7e9b23 | 2013-10-16 22:27:54 -0700 | [diff] [blame] | 314 | } | 
| Elliott Hughes | aa0ebda | 2014-02-11 19:57:06 -0800 | [diff] [blame] | 315 |  | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 316 | static void ClearSignalMask() { | 
 | 317 |   uint64_t sigset = 0; | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 318 |   SignalSetAdd(&sigset, __SIGRTMIN); | 
 | 319 |   if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) { | 
 | 320 |     abort(); | 
 | 321 |   } | 
 | 322 | } | 
 | 323 |  | 
 | 324 | static void FillSignalMask() { | 
 | 325 |   uint64_t sigset = ~0ULL; | 
 | 326 |   for (int signo = __SIGRTMIN + 1; signo < SIGRTMIN; ++signo) { | 
 | 327 |     SignalSetDel(&sigset, signo); | 
 | 328 |   } | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 329 |   if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) { | 
 | 330 |     abort(); | 
 | 331 |   } | 
 | 332 | } | 
 | 333 |  | 
 | 334 | static uint64_t GetSignalMask() { | 
 | 335 |   uint64_t sigset; | 
 | 336 |   if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, nullptr, &sigset, sizeof(sigset)) != 0) { | 
 | 337 |     abort(); | 
 | 338 |   } | 
 | 339 |   return sigset; | 
 | 340 | } | 
 | 341 |  | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 342 | static void TestSignalMaskFiltered(uint64_t sigset) { | 
 | 343 | #if defined(__BIONIC__) | 
 | 344 |   for (int signo = __SIGRTMIN; signo < SIGRTMIN; ++signo) { | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 345 |     bool signal_blocked = sigset & (1ULL << (signo - 1)); | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 346 |     if (signo == __SIGRTMIN) { | 
 | 347 |       // TIMER_SIGNAL must be blocked. | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 348 |       EXPECT_EQ(true, signal_blocked) << "signal " << signo; | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 349 |     } else { | 
 | 350 |       // The other reserved signals must not be blocked. | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 351 |       EXPECT_EQ(false, signal_blocked) << "signal " << signo; | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 352 |     } | 
 | 353 |   } | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 354 | #else | 
 | 355 |   UNUSED(sigset); | 
 | 356 | #endif | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 357 | } | 
 | 358 |  | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 359 | static void TestSignalMaskFunction(std::function<void()> fn) { | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 360 |   ClearSignalMask(); | 
 | 361 |   fn(); | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 362 |   TestSignalMaskFiltered(GetSignalMask()); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 363 | } | 
 | 364 |  | 
 | 365 | TEST(signal, sigaction_filter) { | 
 | 366 |   ClearSignalMask(); | 
 | 367 |   static uint64_t sigset; | 
 | 368 |   struct sigaction sa = {}; | 
 | 369 |   sa.sa_handler = [](int) { sigset = GetSignalMask(); }; | 
| Josh Gao | ba40ff6 | 2019-01-22 22:53:49 -0800 | [diff] [blame] | 370 |   sa.sa_flags = SA_ONSTACK | SA_NODEFER; | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 371 |   sigfillset(&sa.sa_mask); | 
 | 372 |   sigaction(SIGUSR1, &sa, nullptr); | 
 | 373 |   raise(SIGUSR1); | 
| Josh Gao | ba40ff6 | 2019-01-22 22:53:49 -0800 | [diff] [blame] | 374 |  | 
 | 375 |   // On LP32, struct sigaction::sa_mask is only 32-bits wide. | 
 | 376 |   unsigned long expected_sigset = ~0UL; | 
 | 377 |  | 
 | 378 |   // SIGKILL and SIGSTOP are always blocked. | 
 | 379 |   expected_sigset &= ~(1UL << (SIGKILL - 1)); | 
 | 380 |   expected_sigset &= ~(1UL << (SIGSTOP - 1)); | 
 | 381 |  | 
 | 382 |   ASSERT_EQ(static_cast<uint64_t>(expected_sigset), sigset); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 383 | } | 
 | 384 |  | 
 | 385 | TEST(signal, sigaction64_filter) { | 
 | 386 |   ClearSignalMask(); | 
 | 387 |   static uint64_t sigset; | 
 | 388 |   struct sigaction64 sa = {}; | 
 | 389 |   sa.sa_handler = [](int) { sigset = GetSignalMask(); }; | 
| Josh Gao | ba40ff6 | 2019-01-22 22:53:49 -0800 | [diff] [blame] | 390 |   sa.sa_flags = SA_ONSTACK | SA_NODEFER; | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 391 |   sigfillset64(&sa.sa_mask); | 
 | 392 |   sigaction64(SIGUSR1, &sa, nullptr); | 
 | 393 |   raise(SIGUSR1); | 
| Josh Gao | ba40ff6 | 2019-01-22 22:53:49 -0800 | [diff] [blame] | 394 |  | 
 | 395 |   uint64_t expected_sigset = ~0ULL; | 
 | 396 |  | 
 | 397 |   // SIGKILL and SIGSTOP are always blocked. | 
 | 398 |   expected_sigset &= ~(1ULL << (SIGKILL - 1)); | 
 | 399 |   expected_sigset &= ~(1ULL << (SIGSTOP - 1)); | 
 | 400 |  | 
 | 401 |   ASSERT_EQ(expected_sigset, sigset); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 402 | } | 
 | 403 |  | 
 | 404 | TEST(signal, sigprocmask_setmask_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 405 |   TestSignalMaskFunction([]() { | 
 | 406 |     ClearSignalMask(); | 
 | 407 |     sigset_t sigset_libc; | 
 | 408 |     sigfillset(&sigset_libc); | 
 | 409 |     ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &sigset_libc, nullptr)); | 
 | 410 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 411 | } | 
 | 412 |  | 
 | 413 | TEST(signal, sigprocmask64_setmask_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 414 |   TestSignalMaskFunction([]() { | 
 | 415 |     ClearSignalMask(); | 
 | 416 |     sigset64_t sigset_libc; | 
 | 417 |     sigfillset64(&sigset_libc); | 
 | 418 |     ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &sigset_libc, nullptr)); | 
 | 419 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 420 | } | 
 | 421 |  | 
 | 422 | TEST(signal, pthread_sigmask_setmask_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 423 |   TestSignalMaskFunction([]() { | 
 | 424 |     ClearSignalMask(); | 
 | 425 |     sigset_t sigset_libc; | 
 | 426 |     sigfillset(&sigset_libc); | 
 | 427 |     ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &sigset_libc, nullptr)); | 
 | 428 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 429 | } | 
 | 430 |  | 
 | 431 | TEST(signal, pthread_sigmask64_setmask_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 432 |   TestSignalMaskFunction([]() { | 
 | 433 |     ClearSignalMask(); | 
 | 434 |     sigset64_t sigset_libc; | 
 | 435 |     sigfillset64(&sigset_libc); | 
 | 436 |     ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &sigset_libc, nullptr)); | 
 | 437 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 438 | } | 
 | 439 |  | 
 | 440 | TEST(signal, sigprocmask_block_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 441 |   TestSignalMaskFunction([]() { | 
 | 442 |     ClearSignalMask(); | 
 | 443 |     sigset_t sigset_libc; | 
 | 444 |     sigfillset(&sigset_libc); | 
 | 445 |     ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset_libc, nullptr)); | 
 | 446 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 447 | } | 
 | 448 |  | 
 | 449 | TEST(signal, sigprocmask64_block_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 450 |   TestSignalMaskFunction([]() { | 
 | 451 |     ClearSignalMask(); | 
 | 452 |     sigset64_t sigset_libc; | 
 | 453 |     sigfillset64(&sigset_libc); | 
 | 454 |     ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &sigset_libc, nullptr)); | 
 | 455 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 456 | } | 
 | 457 |  | 
 | 458 | TEST(signal, pthread_sigmask_block_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 459 |   TestSignalMaskFunction([]() { | 
 | 460 |     ClearSignalMask(); | 
 | 461 |     sigset_t sigset_libc; | 
 | 462 |     sigfillset(&sigset_libc); | 
 | 463 |     ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &sigset_libc, nullptr)); | 
 | 464 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 465 | } | 
 | 466 |  | 
 | 467 | TEST(signal, pthread_sigmask64_block_filter) { | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 468 |   TestSignalMaskFunction([]() { | 
 | 469 |     ClearSignalMask(); | 
 | 470 |     sigset64_t sigset_libc; | 
 | 471 |     sigfillset64(&sigset_libc); | 
 | 472 |     ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &sigset_libc, nullptr)); | 
 | 473 |   }); | 
 | 474 | } | 
 | 475 |  | 
 | 476 | TEST(signal, sigprocmask_unblock_filter) { | 
 | 477 |   TestSignalMaskFunction([]() { | 
 | 478 |     FillSignalMask(); | 
 | 479 |     sigset_t sigset_libc; | 
 | 480 |     sigfillset(&sigset_libc); | 
 | 481 |     ASSERT_EQ(0, sigprocmask(SIG_UNBLOCK, &sigset_libc, nullptr)); | 
 | 482 |   }); | 
 | 483 | } | 
 | 484 |  | 
 | 485 | TEST(signal, sigprocmask64_unblock_filter) { | 
 | 486 |   TestSignalMaskFunction([]() { | 
 | 487 |     FillSignalMask(); | 
 | 488 |     sigset64_t sigset_libc; | 
 | 489 |     sigfillset64(&sigset_libc); | 
 | 490 |     ASSERT_EQ(0, sigprocmask64(SIG_UNBLOCK, &sigset_libc, nullptr)); | 
 | 491 |   }); | 
 | 492 | } | 
 | 493 |  | 
 | 494 | TEST(signal, pthread_sigmask_unblock_filter) { | 
 | 495 |   TestSignalMaskFunction([]() { | 
 | 496 |     FillSignalMask(); | 
 | 497 |     sigset_t sigset_libc; | 
 | 498 |     sigfillset(&sigset_libc); | 
 | 499 |     ASSERT_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigset_libc, nullptr)); | 
 | 500 |   }); | 
 | 501 | } | 
 | 502 |  | 
 | 503 | TEST(signal, pthread_sigmask64_unblock_filter) { | 
 | 504 |   TestSignalMaskFunction([]() { | 
 | 505 |     FillSignalMask(); | 
 | 506 |     sigset64_t sigset_libc; | 
 | 507 |     sigfillset64(&sigset_libc); | 
 | 508 |     ASSERT_EQ(0, pthread_sigmask64(SIG_UNBLOCK, &sigset_libc, nullptr)); | 
 | 509 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 510 | } | 
 | 511 |  | 
 | 512 | // glibc filters out signals via sigfillset, not the actual underlying functions. | 
 | 513 | TEST(signal, sigset_filter) { | 
 | 514 | #if defined(__BIONIC__) | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 515 |   TestSignalMaskFunction([]() { | 
 | 516 |     for (int i = 1; i <= 64; ++i) { | 
 | 517 |       sigset(i, SIG_HOLD); | 
 | 518 |     } | 
 | 519 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 520 | #endif | 
 | 521 | } | 
 | 522 |  | 
 | 523 | TEST(signal, sighold_filter) { | 
 | 524 | #if defined(__BIONIC__) | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 525 |   TestSignalMaskFunction([]() { | 
 | 526 |     for (int i = 1; i <= 64; ++i) { | 
 | 527 |       sighold(i); | 
 | 528 |     } | 
 | 529 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 530 | #endif | 
 | 531 | } | 
 | 532 |  | 
 | 533 | #if defined(__BIONIC__) | 
 | 534 | // Not exposed via headers, but the symbols are available if you declare them yourself. | 
 | 535 | extern "C" int sigblock(int); | 
 | 536 | extern "C" int sigsetmask(int); | 
 | 537 | #endif | 
 | 538 |  | 
 | 539 | TEST(signal, sigblock_filter) { | 
 | 540 | #if defined(__BIONIC__) | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 541 |   TestSignalMaskFunction([]() { | 
 | 542 |     sigblock(~0U); | 
 | 543 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 544 | #endif | 
 | 545 | } | 
 | 546 |  | 
 | 547 | TEST(signal, sigsetmask_filter) { | 
 | 548 | #if defined(__BIONIC__) | 
| Josh Gao | baf20fc | 2018-10-08 17:28:07 -0700 | [diff] [blame] | 549 |   TestSignalMaskFunction([]() { | 
 | 550 |     sigsetmask(~0U); | 
 | 551 |   }); | 
| Josh Gao | 6fcba93 | 2018-02-09 13:38:32 -0800 | [diff] [blame] | 552 | #endif | 
 | 553 | } | 
 | 554 |  | 
| Elliott Hughes | aa0ebda | 2014-02-11 19:57:06 -0800 | [diff] [blame] | 555 | TEST(signal, sys_signame) { | 
| Elliott Hughes | 671e236 | 2014-02-12 19:04:27 -0800 | [diff] [blame] | 556 | #if defined(__BIONIC__) | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 557 |   ASSERT_TRUE(sys_signame[0] == nullptr); | 
| Elliott Hughes | aa0ebda | 2014-02-11 19:57:06 -0800 | [diff] [blame] | 558 |   ASSERT_STREQ("HUP", sys_signame[SIGHUP]); | 
 | 559 | #else | 
| Elliott Hughes | bcaa454 | 2019-03-08 15:20:23 -0800 | [diff] [blame] | 560 |   GTEST_SKIP() << "glibc doesn't have sys_signame"; | 
| Elliott Hughes | aa0ebda | 2014-02-11 19:57:06 -0800 | [diff] [blame] | 561 | #endif | 
 | 562 | } | 
 | 563 |  | 
 | 564 | TEST(signal, sys_siglist) { | 
| Colin Cross | 4c5595c | 2021-08-16 15:51:59 -0700 | [diff] [blame] | 565 | #if !defined(ANDROID_HOST_MUSL) | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 566 |   ASSERT_TRUE(sys_siglist[0] == nullptr); | 
| Elliott Hughes | aa0ebda | 2014-02-11 19:57:06 -0800 | [diff] [blame] | 567 |   ASSERT_STREQ("Hangup", sys_siglist[SIGHUP]); | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 568 | #else | 
 | 569 |   GTEST_SKIP() << "musl doesn't have sys_siglist"; | 
 | 570 | #endif | 
| Elliott Hughes | aa0ebda | 2014-02-11 19:57:06 -0800 | [diff] [blame] | 571 | } | 
| Elliott Hughes | 0990d4f | 2014-04-30 09:45:40 -0700 | [diff] [blame] | 572 |  | 
 | 573 | TEST(signal, limits) { | 
| Elliott Hughes | 6a65ccd | 2020-02-13 09:48:14 -0800 | [diff] [blame] | 574 |   // These come from the kernel. | 
| Elliott Hughes | 0990d4f | 2014-04-30 09:45:40 -0700 | [diff] [blame] | 575 |   ASSERT_EQ(32, __SIGRTMIN); | 
| Elliott Hughes | 6a65ccd | 2020-02-13 09:48:14 -0800 | [diff] [blame] | 576 |   ASSERT_EQ(64, __SIGRTMAX); | 
| Elliott Hughes | 0990d4f | 2014-04-30 09:45:40 -0700 | [diff] [blame] | 577 |  | 
 | 578 |   // We reserve a non-zero number at the bottom for ourselves. | 
 | 579 |   ASSERT_GT(SIGRTMIN, __SIGRTMIN); | 
 | 580 |  | 
| Elliott Hughes | 0990d4f | 2014-04-30 09:45:40 -0700 | [diff] [blame] | 581 |   // We don't currently reserve any at the top. | 
 | 582 |   ASSERT_EQ(SIGRTMAX, __SIGRTMAX); | 
 | 583 | } | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 584 |  | 
 | 585 | static int g_sigqueue_signal_handler_call_count = 0; | 
 | 586 |  | 
 | 587 | static void SigqueueSignalHandler(int signum, siginfo_t* info, void*) { | 
 | 588 |   ASSERT_EQ(SIGALRM, signum); | 
 | 589 |   ASSERT_EQ(SIGALRM, info->si_signo); | 
 | 590 |   ASSERT_EQ(SI_QUEUE, info->si_code); | 
 | 591 |   ASSERT_EQ(1, info->si_value.sival_int); | 
 | 592 |   ++g_sigqueue_signal_handler_call_count; | 
 | 593 | } | 
 | 594 |  | 
 | 595 | TEST(signal, sigqueue) { | 
 | 596 |   ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 597 |   sigval sigval = {.sival_int = 1}; | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 598 |   errno = 0; | 
 | 599 |   ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); | 
 | 600 |   ASSERT_EQ(0, errno); | 
 | 601 |   ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); | 
 | 602 | } | 
 | 603 |  | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 604 | TEST(signal, pthread_sigqueue_self) { | 
| Colin Cross | 4c5595c | 2021-08-16 15:51:59 -0700 | [diff] [blame] | 605 | #if !defined(ANDROID_HOST_MUSL) | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 606 |   ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 607 |   sigval sigval = {.sival_int = 1}; | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 608 |   errno = 0; | 
 | 609 |   ASSERT_EQ(0, pthread_sigqueue(pthread_self(), SIGALRM, sigval)); | 
 | 610 |   ASSERT_EQ(0, errno); | 
 | 611 |   ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 612 | #else | 
 | 613 |   GTEST_SKIP() << "musl doesn't have pthread_sigqueue"; | 
 | 614 | #endif | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 615 | } | 
 | 616 |  | 
 | 617 | TEST(signal, pthread_sigqueue_other) { | 
| Colin Cross | 4c5595c | 2021-08-16 15:51:59 -0700 | [diff] [blame] | 618 | #if !defined(ANDROID_HOST_MUSL) | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 619 |   ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 620 |   sigval sigval = {.sival_int = 1}; | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 621 |  | 
 | 622 |   sigset_t mask; | 
 | 623 |   sigfillset(&mask); | 
 | 624 |   pthread_sigmask(SIG_SETMASK, &mask, nullptr); | 
 | 625 |   pthread_t thread; | 
 | 626 |   int rc = pthread_create(&thread, nullptr, | 
 | 627 |                           [](void*) -> void* { | 
 | 628 |                             sigset_t mask; | 
 | 629 |                             sigemptyset(&mask); | 
 | 630 |                             sigsuspend(&mask); | 
 | 631 |                             return nullptr; | 
 | 632 |                           }, | 
 | 633 |                           nullptr); | 
 | 634 |   ASSERT_EQ(0, rc); | 
 | 635 |  | 
 | 636 |   errno = 0; | 
 | 637 |   ASSERT_EQ(0, pthread_sigqueue(thread, SIGALRM, sigval)); | 
 | 638 |   ASSERT_EQ(0, errno); | 
 | 639 |   pthread_join(thread, nullptr); | 
 | 640 |   ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 641 | #else | 
 | 642 |   GTEST_SKIP() << "musl doesn't have pthread_sigqueue"; | 
 | 643 | #endif | 
| Josh Gao | 726b63f | 2018-08-27 16:00:58 -0700 | [diff] [blame] | 644 | } | 
 | 645 |  | 
| Elliott Hughes | 50fca4d | 2020-03-20 16:25:54 -0700 | [diff] [blame] | 646 | TEST(signal, sigwait_SIGALRM) { | 
 | 647 |   SignalMaskRestorer smr; | 
 | 648 |  | 
 | 649 |   // Block SIGALRM. | 
 | 650 |   sigset_t just_SIGALRM; | 
 | 651 |   sigemptyset(&just_SIGALRM); | 
 | 652 |   sigaddset(&just_SIGALRM, SIGALRM); | 
 | 653 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); | 
 | 654 |  | 
 | 655 |   // Raise SIGALRM. | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 656 |   sigval sigval = {.sival_int = 1}; | 
| Elliott Hughes | 50fca4d | 2020-03-20 16:25:54 -0700 | [diff] [blame] | 657 |   ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); | 
 | 658 |  | 
 | 659 |   // Get pending SIGALRM. | 
 | 660 |   int sig; | 
 | 661 |   ASSERT_EQ(0, sigwait(&just_SIGALRM, &sig)); | 
 | 662 |   ASSERT_EQ(SIGALRM, sig); | 
 | 663 | } | 
 | 664 |  | 
 | 665 | TEST(signal, sigwait64_SIGRTMIN) { | 
 | 666 |   SignalMaskRestorer smr; | 
 | 667 |  | 
 | 668 |   // Block SIGRTMIN. | 
 | 669 |   sigset64_t just_SIGRTMIN; | 
 | 670 |   sigemptyset64(&just_SIGRTMIN); | 
 | 671 |   sigaddset64(&just_SIGRTMIN, SIGRTMIN); | 
 | 672 |   ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); | 
 | 673 |  | 
 | 674 |   // Raise SIGRTMIN. | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 675 |   sigval sigval = {.sival_int = 1}; | 
| Elliott Hughes | 50fca4d | 2020-03-20 16:25:54 -0700 | [diff] [blame] | 676 |   ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); | 
 | 677 |  | 
 | 678 |   // Get pending SIGRTMIN. | 
 | 679 |   int sig; | 
 | 680 |   ASSERT_EQ(0, sigwait64(&just_SIGRTMIN, &sig)); | 
 | 681 |   ASSERT_EQ(SIGRTMIN, sig); | 
 | 682 | } | 
 | 683 |  | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 684 | TEST(signal, sigwaitinfo) { | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 685 |   SignalMaskRestorer smr; | 
 | 686 |  | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 687 |   // Block SIGALRM. | 
 | 688 |   sigset_t just_SIGALRM; | 
 | 689 |   sigemptyset(&just_SIGALRM); | 
 | 690 |   sigaddset(&just_SIGALRM, SIGALRM); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 691 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 692 |  | 
 | 693 |   // Raise SIGALRM. | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 694 |   sigval sigval = {.sival_int = 1}; | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 695 |   ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); | 
 | 696 |  | 
 | 697 |   // Get pending SIGALRM. | 
 | 698 |   siginfo_t info; | 
 | 699 |   errno = 0; | 
 | 700 |   ASSERT_EQ(SIGALRM, sigwaitinfo(&just_SIGALRM, &info)); | 
 | 701 |   ASSERT_EQ(0, errno); | 
 | 702 |   ASSERT_EQ(SIGALRM, info.si_signo); | 
 | 703 |   ASSERT_EQ(1, info.si_value.sival_int); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 704 | } | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 705 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 706 | TEST(signal, sigwaitinfo64_SIGRTMIN) { | 
 | 707 |   SignalMaskRestorer smr; | 
 | 708 |  | 
 | 709 |   // Block SIGRTMIN. | 
 | 710 |   sigset64_t just_SIGRTMIN; | 
 | 711 |   sigemptyset64(&just_SIGRTMIN); | 
 | 712 |   sigaddset64(&just_SIGRTMIN, SIGRTMIN); | 
 | 713 |   ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); | 
 | 714 |  | 
 | 715 |   // Raise SIGRTMIN. | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 716 |   sigval sigval = {.sival_int = 1}; | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 717 |   ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); | 
 | 718 |  | 
 | 719 |   // Get pending SIGRTMIN. | 
 | 720 |   siginfo_t info; | 
 | 721 |   errno = 0; | 
 | 722 |   ASSERT_EQ(SIGRTMIN, sigwaitinfo64(&just_SIGRTMIN, &info)); | 
 | 723 |   ASSERT_EQ(0, errno); | 
 | 724 |   ASSERT_EQ(SIGRTMIN, info.si_signo); | 
 | 725 |   ASSERT_EQ(1, info.si_value.sival_int); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 726 | } | 
 | 727 |  | 
 | 728 | TEST(signal, sigtimedwait) { | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 729 |   SignalMaskRestorer smr; | 
 | 730 |  | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 731 |   // Block SIGALRM. | 
 | 732 |   sigset_t just_SIGALRM; | 
 | 733 |   sigemptyset(&just_SIGALRM); | 
 | 734 |   sigaddset(&just_SIGALRM, SIGALRM); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 735 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 736 |  | 
 | 737 |   // Raise SIGALRM. | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 738 |   sigval sigval = { .sival_int = 1 }; | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 739 |   ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); | 
 | 740 |  | 
 | 741 |   // Get pending SIGALRM. | 
 | 742 |   siginfo_t info; | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 743 |   timespec timeout = { .tv_sec = 2, .tv_nsec = 0 }; | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 744 |   errno = 0; | 
 | 745 |   ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout)); | 
 | 746 |   ASSERT_EQ(0, errno); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 747 | } | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 748 |  | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 749 | TEST(signal, sigtimedwait64_SIGRTMIN) { | 
 | 750 |   SignalMaskRestorer smr; | 
 | 751 |  | 
 | 752 |   // Block SIGRTMIN. | 
 | 753 |   sigset64_t just_SIGRTMIN; | 
 | 754 |   sigemptyset64(&just_SIGRTMIN); | 
 | 755 |   sigaddset64(&just_SIGRTMIN, SIGRTMIN); | 
 | 756 |   ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); | 
 | 757 |  | 
 | 758 |   // Raise SIGALRM. | 
| Colin Cross | 7da2034 | 2021-07-28 11:18:11 -0700 | [diff] [blame] | 759 |   sigval sigval = { .sival_int = 1 }; | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 760 |   ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); | 
 | 761 |  | 
 | 762 |   // Get pending SIGALRM. | 
 | 763 |   siginfo_t info; | 
 | 764 |   timespec timeout = { .tv_sec = 2, .tv_nsec = 0 }; | 
 | 765 |   errno = 0; | 
 | 766 |   ASSERT_EQ(SIGRTMIN, sigtimedwait64(&just_SIGRTMIN, &info, &timeout)); | 
 | 767 |   ASSERT_EQ(0, errno); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 768 | } | 
 | 769 |  | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 770 | TEST(signal, sigtimedwait_timeout) { | 
 | 771 |   // Block SIGALRM. | 
 | 772 |   sigset_t just_SIGALRM; | 
 | 773 |   sigemptyset(&just_SIGALRM); | 
 | 774 |   sigaddset(&just_SIGALRM, SIGALRM); | 
 | 775 |   sigset_t original_set; | 
 | 776 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); | 
 | 777 |  | 
 | 778 |   // Wait timeout. | 
| Elliott Hughes | ca3f8e4 | 2019-10-28 15:59:38 -0700 | [diff] [blame] | 779 |   auto t0 = std::chrono::steady_clock::now(); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 780 |   siginfo_t info; | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 781 |   timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 }; | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 782 |   errno = 0; | 
 | 783 |   ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout)); | 
 | 784 |   ASSERT_EQ(EAGAIN, errno); | 
| Elliott Hughes | ca3f8e4 | 2019-10-28 15:59:38 -0700 | [diff] [blame] | 785 |   auto t1 = std::chrono::steady_clock::now(); | 
 | 786 |   ASSERT_GE(t1-t0, 1000000ns); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 787 |  | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 788 |   ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, nullptr)); | 
| Yabin Cui | 6348160 | 2014-12-01 17:41:04 -0800 | [diff] [blame] | 789 | } | 
| Josh Gao | 61cf3f3 | 2016-03-08 15:27:15 -0800 | [diff] [blame] | 790 |  | 
 | 791 | #if defined(__BIONIC__) | 
 | 792 | TEST(signal, rt_tgsigqueueinfo) { | 
 | 793 |   // Test whether rt_tgsigqueueinfo allows sending arbitrary si_code values to self. | 
 | 794 |   // If this fails, your kernel needs commit 66dd34a to be backported. | 
 | 795 |   static constexpr char error_msg[] = | 
 | 796 |     "\nPlease ensure that the following kernel patch has been applied:\n" | 
 | 797 |     "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921\n"; | 
 | 798 |   static siginfo received; | 
 | 799 |  | 
| Elliott Hughes | 3e23591 | 2018-02-01 14:21:51 -0800 | [diff] [blame] | 800 |   struct sigaction handler = {}; | 
| Josh Gao | 61cf3f3 | 2016-03-08 15:27:15 -0800 | [diff] [blame] | 801 |   handler.sa_sigaction = [](int, siginfo_t* siginfo, void*) { received = *siginfo; }; | 
 | 802 |   handler.sa_flags = SA_SIGINFO; | 
 | 803 |  | 
 | 804 |   ASSERT_EQ(0, sigaction(SIGUSR1, &handler, nullptr)); | 
 | 805 |  | 
| Josh Gao | d787852 | 2016-03-14 18:15:15 -0700 | [diff] [blame] | 806 |   siginfo sent; | 
 | 807 |   memset(&sent, 0, sizeof(sent)); | 
| Josh Gao | 61cf3f3 | 2016-03-08 15:27:15 -0800 | [diff] [blame] | 808 |  | 
 | 809 |   sent.si_code = SI_TKILL; | 
 | 810 |   ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent)) | 
 | 811 |     << "rt_tgsigqueueinfo failed: " << strerror(errno) << error_msg; | 
 | 812 |   ASSERT_EQ(sent.si_code, received.si_code) << "rt_tgsigqueueinfo modified si_code, expected " | 
 | 813 |                                             << sent.si_code << ", received " << received.si_code | 
 | 814 |                                             << error_msg; | 
 | 815 |  | 
 | 816 |   sent.si_code = SI_USER; | 
 | 817 |   ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent)) | 
 | 818 |     << "rt_tgsigqueueinfo failed: " << strerror(errno) << error_msg; | 
 | 819 |   ASSERT_EQ(sent.si_code, received.si_code) << "rt_tgsigqueueinfo modified si_code, expected " | 
 | 820 |                                             << sent.si_code << ", received " << received.si_code | 
 | 821 |                                             << error_msg; | 
 | 822 | } | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 823 | #endif | 
| Josh Gao | c244fcb | 2016-03-29 14:34:03 -0700 | [diff] [blame] | 824 |  | 
| Josh Gao | c244fcb | 2016-03-29 14:34:03 -0700 | [diff] [blame] | 825 | TEST(signal, sigset_size) { | 
| Elliott Hughes | fc03503 | 2022-11-11 22:52:04 +0000 | [diff] [blame] | 826 |   // The setjmp implementations assume that sigset_t can fit in a long. | 
 | 827 |   // This is true because the 32-bit ABIs have broken rt signal support, | 
 | 828 |   // but the 64-bit ABIs both have a SIGRTMAX defined as 64. | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 829 | #if defined(__BIONIC__) | 
| Josh Gao | c244fcb | 2016-03-29 14:34:03 -0700 | [diff] [blame] | 830 |   static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long"); | 
| Elliott Hughes | 5905d6f | 2018-01-30 15:09:51 -0800 | [diff] [blame] | 831 | #endif | 
 | 832 |   static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals"); | 
| Josh Gao | c244fcb | 2016-03-29 14:34:03 -0700 | [diff] [blame] | 833 | } | 
 | 834 |  | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 835 | TEST(signal, sigignore_EINVAL) { | 
 | 836 |   errno = 0; | 
 | 837 |   ASSERT_EQ(-1, sigignore(99999)); | 
 | 838 |   ASSERT_EQ(EINVAL, errno); | 
 | 839 | } | 
 | 840 |  | 
 | 841 | TEST(signal, sigignore) { | 
 | 842 |   errno = 0; | 
 | 843 |   EXPECT_EQ(-1, sigignore(SIGKILL)); | 
 | 844 |   EXPECT_EQ(errno, EINVAL); | 
 | 845 |  | 
 | 846 |   errno = 0; | 
 | 847 |   EXPECT_EQ(-1, sigignore(SIGSTOP)); | 
 | 848 |   EXPECT_EQ(errno, EINVAL); | 
 | 849 |  | 
 | 850 |   ScopedSignalHandler sigalrm{SIGALRM}; | 
 | 851 |   ASSERT_EQ(0, sigignore(SIGALRM)); | 
 | 852 |  | 
 | 853 |   struct sigaction sa; | 
 | 854 |   ASSERT_EQ(0, sigaction(SIGALRM, nullptr, &sa)); | 
 | 855 |   EXPECT_EQ(SIG_IGN, sa.sa_handler); | 
 | 856 | } | 
 | 857 |  | 
 | 858 | TEST(signal, sighold_EINVAL) { | 
 | 859 |   errno = 0; | 
 | 860 |   ASSERT_EQ(-1, sighold(99999)); | 
 | 861 |   ASSERT_EQ(EINVAL, errno); | 
 | 862 | } | 
 | 863 |  | 
 | 864 | TEST(signal, sigpause_EINVAL) { | 
 | 865 |   errno = 0; | 
 | 866 |   ASSERT_EQ(-1, sigpause(99999)); | 
 | 867 |   ASSERT_EQ(EINVAL, errno); | 
 | 868 | } | 
 | 869 |  | 
 | 870 | TEST(signal, sigrelse_EINVAL) { | 
 | 871 |   errno = 0; | 
 | 872 |   ASSERT_EQ(-1, sigpause(99999)); | 
 | 873 |   ASSERT_EQ(EINVAL, errno); | 
 | 874 | } | 
 | 875 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 876 | static void TestSigholdSigpauseSigrelse(int sig) { | 
 | 877 |   static int signal_handler_call_count = 0; | 
 | 878 |   ScopedSignalHandler ssh{sig, [](int) { signal_handler_call_count++; }}; | 
 | 879 |   SignalMaskRestorer mask_restorer; | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 880 |   sigset_t set; | 
 | 881 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 882 |   // sighold(SIGALRM/SIGRTMIN) should add SIGALRM/SIGRTMIN to the signal mask ... | 
 | 883 |   ASSERT_EQ(0, sighold(sig)); | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 884 |   ASSERT_EQ(0, sigprocmask(SIG_SETMASK, nullptr, &set)); | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 885 |   EXPECT_TRUE(sigismember(&set, sig)); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 886 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 887 |   // ... preventing our SIGALRM/SIGRTMIN handler from running ... | 
 | 888 |   raise(sig); | 
 | 889 |   ASSERT_EQ(0, signal_handler_call_count); | 
 | 890 |   // ... until sigpause(SIGALRM/SIGRTMIN) temporarily unblocks it. | 
 | 891 |   ASSERT_EQ(-1, sigpause(sig)); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 892 |   ASSERT_EQ(EINTR, errno); | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 893 |   ASSERT_EQ(1, signal_handler_call_count); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 894 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 895 |   if (sig >= SIGRTMIN && sizeof(void*) == 8) { | 
 | 896 |     // But sigpause(SIGALRM/SIGRTMIN) shouldn't permanently unblock SIGALRM/SIGRTMIN. | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 897 |     ASSERT_EQ(0, sigprocmask(SIG_SETMASK, nullptr, &set)); | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 898 |     EXPECT_TRUE(sigismember(&set, sig)); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 899 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 900 |     // Whereas sigrelse(SIGALRM/SIGRTMIN) should. | 
 | 901 |     ASSERT_EQ(0, sigrelse(sig)); | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 902 |     ASSERT_EQ(0, sigprocmask(SIG_SETMASK, nullptr, &set)); | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 903 |     EXPECT_FALSE(sigismember(&set, sig)); | 
 | 904 |   } else { | 
 | 905 |     // sigismember won't work for SIGRTMIN on LP32. | 
 | 906 |   } | 
 | 907 | } | 
 | 908 |  | 
 | 909 | TEST(signal, sighold_sigpause_sigrelse) { | 
 | 910 |   TestSigholdSigpauseSigrelse(SIGALRM); | 
 | 911 | } | 
 | 912 |  | 
 | 913 | TEST(signal, sighold_sigpause_sigrelse_RT) { | 
 | 914 |   TestSigholdSigpauseSigrelse(SIGRTMIN); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 915 | } | 
 | 916 |  | 
 | 917 | TEST(signal, sigset_EINVAL) { | 
 | 918 |   errno = 0; | 
 | 919 |   ASSERT_EQ(SIG_ERR, sigset(99999, SIG_DFL)); | 
 | 920 |   ASSERT_EQ(EINVAL, errno); | 
 | 921 | } | 
 | 922 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 923 | TEST(signal, sigset_RT) { | 
 | 924 |   static int signal_handler_call_count = 0; | 
 | 925 |   auto signal_handler = [](int) { signal_handler_call_count++; }; | 
 | 926 |   ScopedSignalHandler ssh{SIGRTMIN, signal_handler}; | 
 | 927 |   SignalMaskRestorer mask_restorer; | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 928 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 929 |   ASSERT_EQ(signal_handler, sigset(SIGRTMIN, SIG_HOLD)); | 
 | 930 | #if defined(__LP64__) | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 931 |   sigset_t set; | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 932 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set)); | 
 | 933 |   ASSERT_TRUE(sigismember(&set, SIGRTMIN)); | 
 | 934 | #endif | 
 | 935 |  | 
 | 936 |   ASSERT_EQ(SIG_HOLD, sigset(SIGRTMIN, signal_handler)); | 
 | 937 |   ASSERT_EQ(signal_handler, sigset(SIGRTMIN, signal_handler)); | 
 | 938 |   ASSERT_EQ(0, signal_handler_call_count); | 
 | 939 |   raise(SIGRTMIN); | 
 | 940 |   ASSERT_EQ(1, signal_handler_call_count); | 
 | 941 | } | 
 | 942 |  | 
 | 943 | TEST(signal, sigset) { | 
 | 944 |   static int signal_handler_call_count = 0; | 
 | 945 |   auto signal_handler = [](int) { signal_handler_call_count++; }; | 
 | 946 |   ScopedSignalHandler ssh{SIGALRM, signal_handler}; | 
 | 947 |   SignalMaskRestorer mask_restorer; | 
 | 948 |  | 
 | 949 |   ASSERT_EQ(0, signal_handler_call_count); | 
 | 950 |   raise(SIGALRM); | 
 | 951 |   ASSERT_EQ(1, signal_handler_call_count); | 
 | 952 |  | 
 | 953 |   // Block SIGALRM so the next sigset(SIGARLM) call will return SIG_HOLD. | 
 | 954 |   sigset_t set; | 
 | 955 |   sigemptyset(&set); | 
 | 956 |   sigaddset(&set, SIGALRM); | 
 | 957 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &set, nullptr)); | 
 | 958 |  | 
 | 959 |   sigemptyset(&set); | 
 | 960 |   ASSERT_EQ(SIG_HOLD, sigset(SIGALRM, signal_handler)); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 961 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set)); | 
 | 962 |   EXPECT_FALSE(sigismember(&set, SIGALRM)); | 
 | 963 |  | 
| Elliott Hughes | 4b1c6e7 | 2018-01-24 18:54:38 -0800 | [diff] [blame] | 964 |   ASSERT_EQ(signal_handler, sigset(SIGALRM, SIG_IGN)); | 
| Greg Hackmann | 5375bf6 | 2016-02-29 12:35:33 -0800 | [diff] [blame] | 965 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set)); | 
 | 966 |   EXPECT_FALSE(sigismember(&set, SIGALRM)); | 
 | 967 |  | 
 | 968 |   ASSERT_EQ(SIG_IGN, sigset(SIGALRM, SIG_DFL)); | 
 | 969 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set)); | 
 | 970 |   EXPECT_FALSE(sigismember(&set, SIGALRM)); | 
 | 971 |  | 
 | 972 |   ASSERT_EQ(SIG_DFL, sigset(SIGALRM, SIG_HOLD)); | 
 | 973 |   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set)); | 
 | 974 |   EXPECT_TRUE(sigismember(&set, SIGALRM)); | 
 | 975 | } | 
| Elliott Hughes | 7532b32 | 2017-07-11 15:00:17 -0700 | [diff] [blame] | 976 |  | 
 | 977 | TEST(signal, killpg_EINVAL) { | 
 | 978 |   // POSIX leaves pgrp <= 1 undefined, but glibc fails with EINVAL for < 0 | 
 | 979 |   // and passes 0 through to kill(2). | 
 | 980 |   errno = 0; | 
 | 981 |   ASSERT_EQ(-1, killpg(-1, SIGKILL)); | 
 | 982 |   ASSERT_EQ(EINVAL, errno); | 
 | 983 | } |