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