1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <unistd.h> 17#include <string.h> 18#include <sys/types.h> 19#include <sys/shm.h> 20#include <fcntl.h> 21#include "log.h" 22#include "utils.h" 23#include "SignalTest.h" 24 25using namespace testing::ext; 26 27// static member must init before use. 28int IpcSignalTest::mReceivedSignal = 0; 29int IpcSignalTest::mShmid = 0; 30siginfo_t IpcSignalTest::mSiginfo; 31 32 33// special signal handler for function 'abort' 34void IpcSignalTest::SigAbortHandler(int signum) 35{ 36 LOG("handler: recv a signal: %d", signum); 37 int *shared = static_cast<int*>(shmat(mShmid, nullptr, 0)); 38 if (shared == reinterpret_cast<int*>(-1)) { 39 LOG("SigAbortHandler: shmat fail, errno = %d", errno); 40 } else { 41 LOG("shared: %p", shared); 42 *shared = signum; 43 if (shmdt(shared) == -1) { 44 LOG("SigAbortHandler: shmdt errno = %d", errno); 45 } 46 } 47} 48 49// special signal handler for function 'sigaction' 50void IpcSignalTest::SigactionHandler(int signum, siginfo_t* si, void* ucontext) 51{ 52 LOG("handler recv a signal: %s(%d)", ALL_SIGNALS[signum].signame, signum); 53 mReceivedSignal = signum; 54 // siginfo_t para is not supported yet 55} 56 57// general signal handler. note: not thread-safe 58void IpcSignalTest::SignalHandler(int signum) 59{ 60 LOG("handler recv a signal: %s(%d)", ALL_SIGNALS[signum].signame, signum); 61 mReceivedSignal = signum; 62} 63 64SignalNameAction const ALL_SIGNALS[MAX_SIGNAL] = { 65 {"NA", "Unknown signal", TERMINATE}, 66 {"SIGHUP", "Hangup", TERMINATE}, // 1 67 {"SIGINT", "Interrupt", TERMINATE}, 68 {"SIGQUIT", "Quit", COREDUMP}, 69 {"SIGILL", "Illegal instruction", COREDUMP}, 70 {"SIGTRAP", "Trace/breakpoint trap", COREDUMP}, 71 {"SIGABRT", "Aborted", COREDUMP}, // alias: SIGIOT 72 {"SIGBUS", "Bus error", COREDUMP}, 73 {"SIGFPE", "Arithmetic exception", COREDUMP}, 74 {"SIGKILL", "Killed", TERMINATE}, 75 {"SIGUSR1", "User defined signal 1", TERMINATE}, // 10 76 {"SIGSEGV", "Segmentation fault", COREDUMP}, 77 {"SIGUSR2", "User defined signal 2", TERMINATE}, 78 {"SIGPIPE", "Broken pipe", TERMINATE}, 79 {"SIGALRM", "Alarm clock", TERMINATE}, 80 {"SIGTERM", "Terminated", TERMINATE}, 81 {"SIGSTKFLT", "Stack fault", TERMINATE}, 82 {"SIGCHLD", "Child process status", IGNORE}, // alias: SIGCLD 83 {"SIGCONT", "Continued", CONTINUE}, 84 {"SIGSTOP", "Stopped (signal)", STOP}, 85 {"SIGTSTP", "Stopped", STOP}, // 20 86 {"SIGTTIN", "Stopped (tty input)", STOP}, 87 {"SIGTTOU", "Stopped (tty output)", STOP}, 88 {"SIGURG", "Urgent I/O condition", IGNORE}, 89 {"SIGXCPU", "CPU time limit exceeded", COREDUMP}, 90 {"SIGXFSZ", "File size limit exceeded", COREDUMP}, 91 {"SIGVTALRM", "Virtual timer expired", TERMINATE}, 92 {"SIGPROF", "Profiling timer expired", TERMINATE}, 93 {"SIGWINCH", "Window changed", IGNORE}, 94 {"SIGIO", "I/O possible", TERMINATE}, // alias: SIGPOLL 95 {"SIGPWR", "Power failure", TERMINATE}, // alias: SIGINFO, 30 96}; 97 98void IpcSignalTest::DefaultActionTest(const int signum, const bool expectStop, const bool coredump) 99{ 100 pid_t pid = fork(); 101 ASSERT_TRUE(pid >= 0) << "======== Fork Error! ========="; 102 if (pid > 0) { // parent 103 Msleep(20); 104 LOGD("before kill"); 105 kill(pid, signum); 106 if (!expectStop) { 107 Msleep(20); 108 AssertProcAlive(pid); 109 Msleep(20); 110 WaitProcExitedOK(pid); 111 } else { 112 WaitProcKilled(pid, signum); 113 if (coredump) { 114 // check codedump, liteos not support yet 115 } 116 } 117 } else { // child 118 LOGD("child start"); 119 KeepRun(KEEP_RUN_TIME); 120 if (expectStop) { 121 LOG("Child should has been Terminated, but still alive."); 122 exit(1); 123 } 124 exit(0); 125 } 126} 127 128void IpcSignalTest::SendAndRecvTest(const int signum) 129{ 130 pid_t pid1, pid2; 131 bool useBrother = GetRandom(100) % 2; // if use brother to send the signal 132 pid1 = fork(); 133 ASSERT_TRUE(pid1 >= 0) << "======== Fork1 Error! ========="; 134 if (pid1 > 0) { // parent 135 LOGD("in parent..."); 136 if (useBrother) { 137 pid2 = fork(); 138 ASSERT_TRUE(pid2 >= 0) << "======== Fork2 Error! ========="; 139 if (pid2 == 0) { // child 2 140 Msleep(50); 141 kill(pid1, signum); 142 exit(0); 143 } 144 // parent 145 Msleep(20); 146 LOG("check if child2 exited OK"); 147 WaitProcExitedOK(pid2); 148 } else { 149 Msleep(100); 150 kill(pid1, signum); 151 } 152 AssertProcAlive(pid1); 153 154 Msleep(20); // child should exited now 155 LOG("check if child exited OK"); 156 WaitProcExitedOK(pid1); 157 } else { // child 1, the receiver 158 LOGD("in child, pid=%d", getpid()); 159 handler_type rt = signal(signum, SignalHandler); 160 if (rt == SIG_ERR) { 161 LOG("set %d signal handler failed, errno=%d", signum, errno); 162 exit(1); 163 } 164 Msleep(150); 165 if (mReceivedSignal != signum) { 166 LOG("SignalHandler check fail, expected=%d, received=%d", signum, mReceivedSignal); 167 exit(1); 168 } 169 LOGD("child sleeping...."); 170 Msleep(20); 171 LOGD("child exit 0...."); 172 exit(0); 173 } 174} 175 176int IpcSignalTest::CheckSigString(const char* outfile, const char* expectStr) 177{ 178 const int bufLen = 64; 179 char buffer[bufLen]; 180 181 FILE *fp = fopen(outfile, "rb"); 182 size_t bytes = fread(buffer, 1, bufLen, fp); 183 buffer[bytes] = 0; 184 LOGD("%d bytes read from logfile:%s", bytes, buffer); 185 fclose(fp); 186 size_t expectLen = strlen(expectStr); 187 LOGD("expect string len = %d", expectLen); 188 if (bytes != (expectLen + 1)) { 189 LOG("bytes number read from stderr file error, expect:%d, actual:%d", 190 expectLen + 1, bytes); 191 return 1; 192 } 193 return strncmp(expectStr, buffer, expectLen); 194} 195 196void IpcSignalTest::SignalFailTest(int signum, handler_type h, int expectErrno) 197{ 198 errno = 0; 199 handler_type rt = signal(signum, h); 200 ASSERT_EQ(rt, SIG_ERR) << "signal error for " << signum; 201 ASSERT_EQ(errno, expectErrno) << "signal error for " << signum; 202} 203void IpcSignalTest::SigpendingFailTest(sigset_t* pset) 204{ 205 errno = 0; 206 int rt = sigpending(pset); 207 ASSERT_EQ(rt, -1); 208 ASSERT_EQ(errno, EFAULT); 209} 210void IpcSignalTest::SigtimedwaitFailTest(const sigset_t *set, siginfo_t* info, const timespec* timeout, int expectErrno) 211{ 212 errno = 0; 213 int rt = sigtimedwait(set, info, timeout); 214 ASSERT_EQ(rt, -1); 215 ASSERT_EQ(errno, expectErrno); 216} 217 218// thread function for testcase: 'testPthreadkill' 219void* IpcSignalTest::ThreadFunc1(void* arg) 220{ 221 int sigNo = (int)((uintptr_t)arg); 222 signal(sigNo, SignalHandler); 223 Msleep(60); 224 return nullptr; 225} 226 227// thread function for testcase: 'testPthreadkillMain' 228void* IpcSignalTest::ThreadFunc2(void* arg) 229{ 230 pthread_t* tid = (pthread_t*)arg; 231 int ret = pthread_kill(*tid, SIGINT); 232 if (ret != 0) { 233 LOG("pthread_kill failed, errno=%d", ret); 234 return (void*)1; 235 } 236 LOG("pthread_kill send signal(%d) ok", SIGINT); 237 return nullptr; 238} 239 240// thread function for testcase: 'testPthreadSigmask' 241void* IpcSignalTest::ThreadFuncForSigmask1(void* arg) 242{ 243 int rt; 244 int type = (int)((uintptr_t)arg); 245 if (type == 1) { 246 signal(SIGINT, SignalHandler); 247 } 248 249 LOG("block SIGINT"); 250 sigset_t sigmask, oldmask; 251 sigemptyset(&sigmask); 252 sigemptyset(&oldmask); 253 sigaddset(&sigmask, SIGINT); 254 sigaddset(&sigmask, SIGUSR1); 255 rt = pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); 256 EXPECT_EQ(rt, 0); 257 raise(SIGINT); 258 EXPECT_EQ(mReceivedSignal, 0) << "SignalHandler check fail, SIGINT should has blocked!"; 259 260 LOG("unblock SIGINT"); 261 sigemptyset(&sigmask); 262 sigaddset(&sigmask, SIGINT); 263 rt = pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr); 264 EXPECT_EQ(rt, 0); 265 266 LOG("check the new block set"); 267 sigemptyset(&oldmask); 268 pthread_sigmask(SIG_UNBLOCK, nullptr, &oldmask); 269 EXPECT_EQ(sigismember(&oldmask, SIGINT), 0) << "SIGINT should has deleted from block set!"; 270 EXPECT_EQ(sigismember(&oldmask, SIGUSR1), 1) << "SIGUSR1 should still in block set!"; 271 272 EXPECT_EQ(mReceivedSignal, SIGINT) << "SignalHandler check fail, SIGINT should deliver after unblock!"; 273 return nullptr; 274} 275 276// thread function for testcase: 'testPthreadSigmaskInherit' 277void* IpcSignalTest::ThreadFuncForSigmask2(void* arg) 278{ 279 sigset_t sigmask, oldmask; 280 sigemptyset(&sigmask); 281 sigemptyset(&oldmask); 282 283 LOG("SubThread: check the block set is inherited"); 284 pthread_sigmask(SIG_BLOCK, nullptr, &oldmask); 285 if (!sigismember(&oldmask, SIGUSR1)) { 286 LOG("initial block set should include SIGUSR1!"); 287 return (void*)1; 288 } 289 290 LOG("SubThread: add SIGINT to block set"); 291 sigaddset(&sigmask, SIGINT); 292 int rt = pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); 293 EXPECT_EQ(rt, 0); 294 295 LOG("SubThread: check the new block set"); 296 sigemptyset(&oldmask); 297 pthread_sigmask(SIG_UNBLOCK, nullptr, &oldmask); 298 if (!sigismember(&oldmask, SIGINT)) { 299 LOG("failed to add SIGINT to block set!"); 300 return (void*)1; 301 } 302 if (!sigismember(&oldmask, SIGUSR1)) { 303 LOG("SIGUSR1 should still in block set!"); 304 return (void*)1; 305 } 306 return nullptr; 307}