1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* 21f08c3bdfSopenharmony_ci * NAME 22f08c3bdfSopenharmony_ci * sigaction01.c 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * DESCRIPTION 25f08c3bdfSopenharmony_ci * Test some features of sigaction (see below for more details) 26f08c3bdfSopenharmony_ci * 27f08c3bdfSopenharmony_ci * ALGORITHM 28f08c3bdfSopenharmony_ci * Use sigaction(2) to set a signal handler for SIGUSR1 with a certain 29f08c3bdfSopenharmony_ci * set of flags, set a global variable indicating the test case, and 30f08c3bdfSopenharmony_ci * finally send the signal to ourselves, causing the signal handler to 31f08c3bdfSopenharmony_ci * run. The signal handler then checks the signal handler to run. The 32f08c3bdfSopenharmony_ci * signal handler then checks certain conditions based on the test case 33f08c3bdfSopenharmony_ci * number. 34f08c3bdfSopenharmony_ci * There are 4 test cases: 35f08c3bdfSopenharmony_ci * 36f08c3bdfSopenharmony_ci * 1) Set SA_RESETHAND and SA_SIGINFO. When the handler runs, 37f08c3bdfSopenharmony_ci * SA_SIGINFO should be set. 38f08c3bdfSopenharmony_ci * 39f08c3bdfSopenharmony_ci * 2) Set SA_RESETHAND. When the handler runs, SIGUSR1 should be 40f08c3bdfSopenharmony_ci * masked (SA_RESETHAND makes sigaction behave as if SA_NODEFER was 41f08c3bdfSopenharmony_ci * not set). 42f08c3bdfSopenharmony_ci * 43f08c3bdfSopenharmony_ci * 3) Same as case #2, but when the handler is established, sa_mask is 44f08c3bdfSopenharmony_ci * set to include SIGUSR1. Ensure that SIGUSR1 is indeed masked even if 45f08c3bdfSopenharmony_ci * SA_RESETHAND is set. 46f08c3bdfSopenharmony_ci * 47f08c3bdfSopenharmony_ci * 4) A signal generated from an interface or condition that does not 48f08c3bdfSopenharmony_ci * provide siginfo (such as pthread_kill(3)) should invoke the handler 49f08c3bdfSopenharmony_ci * with a non-NULL siginfo pointer. 50f08c3bdfSopenharmony_ci * 51f08c3bdfSopenharmony_ci * USAGE: <for command-line> 52f08c3bdfSopenharmony_ci * sigaction01 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 53f08c3bdfSopenharmony_ci * where, -c n : Run n copies concurrently. 54f08c3bdfSopenharmony_ci * -f : Turn off functionality Testing. 55f08c3bdfSopenharmony_ci * -i n : Execute test n times. 56f08c3bdfSopenharmony_ci * -I x : Execute test for x seconds. 57f08c3bdfSopenharmony_ci * -P x : Pause for x seconds between iterations. 58f08c3bdfSopenharmony_ci * -t : Turn on syscall timing. 59f08c3bdfSopenharmony_ci * 60f08c3bdfSopenharmony_ci * HISTORY 61f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer 62f08c3bdfSopenharmony_ci * 63f08c3bdfSopenharmony_ci * RESTRICTIONS 64f08c3bdfSopenharmony_ci * NONE 65f08c3bdfSopenharmony_ci */ 66f08c3bdfSopenharmony_ci#include <pthread.h> 67f08c3bdfSopenharmony_ci#include <signal.h> 68f08c3bdfSopenharmony_ci#include <errno.h> 69f08c3bdfSopenharmony_ci#include <stdlib.h> 70f08c3bdfSopenharmony_ci#include <unistd.h> 71f08c3bdfSopenharmony_ci#include "test.h" 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_civoid setup(); 74f08c3bdfSopenharmony_civoid cleanup(); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_cichar *TCID = "sigaction01"; 77f08c3bdfSopenharmony_ciint TST_TOTAL = 4; 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_civolatile sig_atomic_t testcase_no; 80f08c3bdfSopenharmony_civolatile sig_atomic_t pass; 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci/* 83f08c3bdfSopenharmony_ci * handler() 84f08c3bdfSopenharmony_ci * 85f08c3bdfSopenharmony_ci * A signal handler that understands which test case is currently 86f08c3bdfSopenharmony_ci * being executed and compares the current conditions to the ones it 87f08c3bdfSopenharmony_ci * expects (based on the test case number). 88f08c3bdfSopenharmony_ci */ 89f08c3bdfSopenharmony_civoid handler(int sig, siginfo_t * sip, void *ucp) 90f08c3bdfSopenharmony_ci{ 91f08c3bdfSopenharmony_ci struct sigaction oact; 92f08c3bdfSopenharmony_ci int err; 93f08c3bdfSopenharmony_ci sigset_t nmask, omask; 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci /* 96f08c3bdfSopenharmony_ci * Get sigaction setting 97f08c3bdfSopenharmony_ci */ 98f08c3bdfSopenharmony_ci err = sigaction(SIGUSR1, NULL, &oact); 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci if (err == -1) { 101f08c3bdfSopenharmony_ci perror("sigaction"); 102f08c3bdfSopenharmony_ci return; 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci /* 106f08c3bdfSopenharmony_ci * Get current signal mask 107f08c3bdfSopenharmony_ci */ 108f08c3bdfSopenharmony_ci sigemptyset(&nmask); 109f08c3bdfSopenharmony_ci sigemptyset(&omask); 110f08c3bdfSopenharmony_ci err = sigprocmask(SIG_BLOCK, &nmask, &omask); 111f08c3bdfSopenharmony_ci if (err == -1) { 112f08c3bdfSopenharmony_ci perror("sigprocmask"); 113f08c3bdfSopenharmony_ci tst_resm(TWARN, "sigprocmask() failed"); 114f08c3bdfSopenharmony_ci return; 115f08c3bdfSopenharmony_ci } 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci switch (testcase_no) { 118f08c3bdfSopenharmony_ci case 1: 119f08c3bdfSopenharmony_ci /* 120f08c3bdfSopenharmony_ci * SA_RESETHAND and SA_SIGINFO were set. SA_SIGINFO should 121f08c3bdfSopenharmony_ci * be clear in Linux. In Linux kernel, SA_SIGINFO is not 122f08c3bdfSopenharmony_ci * cleared in psig(). 123f08c3bdfSopenharmony_ci */ 124f08c3bdfSopenharmony_ci if (!(oact.sa_flags & SA_SIGINFO)) { 125f08c3bdfSopenharmony_ci tst_resm(TFAIL, "SA_RESETHAND should not " 126f08c3bdfSopenharmony_ci "cause SA_SIGINFO to be cleared, but it was."); 127f08c3bdfSopenharmony_ci return; 128f08c3bdfSopenharmony_ci } 129f08c3bdfSopenharmony_ci if (sip == NULL) { 130f08c3bdfSopenharmony_ci tst_resm(TFAIL, "siginfo should not be NULL"); 131f08c3bdfSopenharmony_ci return; 132f08c3bdfSopenharmony_ci } 133f08c3bdfSopenharmony_ci tst_resm(TPASS, "SA_RESETHAND did not " 134f08c3bdfSopenharmony_ci "cause SA_SIGINFO to be cleared"); 135f08c3bdfSopenharmony_ci break; 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci case 2: 138f08c3bdfSopenharmony_ci /* 139f08c3bdfSopenharmony_ci * In Linux, SA_RESETHAND doesn't imply SA_NODEFER; sig 140f08c3bdfSopenharmony_ci * should not be masked. The testcase should pass if 141f08c3bdfSopenharmony_ci * SA_NODEFER is not masked, ie. if SA_NODEFER is a member 142f08c3bdfSopenharmony_ci * of the signal list 143f08c3bdfSopenharmony_ci */ 144f08c3bdfSopenharmony_ci if (sigismember(&omask, sig) == 0) { 145f08c3bdfSopenharmony_ci tst_resm(TFAIL, "SA_RESETHAND should cause sig to " 146f08c3bdfSopenharmony_ci "be masked when the handler executes."); 147f08c3bdfSopenharmony_ci return; 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci tst_resm(TPASS, "SA_RESETHAND was masked when handler " 150f08c3bdfSopenharmony_ci "executed"); 151f08c3bdfSopenharmony_ci break; 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci case 3: 154f08c3bdfSopenharmony_ci /* 155f08c3bdfSopenharmony_ci * SA_RESETHAND implies SA_NODEFER unless sa_mask already 156f08c3bdfSopenharmony_ci * included sig. 157f08c3bdfSopenharmony_ci */ 158f08c3bdfSopenharmony_ci if (!sigismember(&omask, sig)) { 159f08c3bdfSopenharmony_ci tst_resm(TFAIL, "sig should continue to be masked " 160f08c3bdfSopenharmony_ci "because sa_mask originally contained sig."); 161f08c3bdfSopenharmony_ci return; 162f08c3bdfSopenharmony_ci } 163f08c3bdfSopenharmony_ci tst_resm(TPASS, "sig has been masked " 164f08c3bdfSopenharmony_ci "because sa_mask originally contained sig"); 165f08c3bdfSopenharmony_ci break; 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci case 4: 168f08c3bdfSopenharmony_ci /* 169f08c3bdfSopenharmony_ci * A signal generated from a mechanism that does not provide 170f08c3bdfSopenharmony_ci * siginfo should invoke the handler with a non-NULL siginfo 171f08c3bdfSopenharmony_ci * pointer. 172f08c3bdfSopenharmony_ci */ 173f08c3bdfSopenharmony_ci if (sip == NULL) { 174f08c3bdfSopenharmony_ci tst_resm(TFAIL, "siginfo pointer should not be NULL"); 175f08c3bdfSopenharmony_ci return; 176f08c3bdfSopenharmony_ci } 177f08c3bdfSopenharmony_ci tst_resm(TPASS, "siginfo pointer non NULL"); 178f08c3bdfSopenharmony_ci break; 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci default: 181f08c3bdfSopenharmony_ci tst_resm(TFAIL, "invalid test case number: %d", testcase_no); 182f08c3bdfSopenharmony_ci exit(1); 183f08c3bdfSopenharmony_ci } 184f08c3bdfSopenharmony_ci} 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci/* 187f08c3bdfSopenharmony_ci * set_handler() 188f08c3bdfSopenharmony_ci * 189f08c3bdfSopenharmony_ci * Establish a signal handler for SIGUSR1 with the specified flags and 190f08c3bdfSopenharmony_ci * signal to mask while the handler executes. 191f08c3bdfSopenharmony_ci */ 192f08c3bdfSopenharmony_ciint set_handler(int flags, int sig_to_mask) 193f08c3bdfSopenharmony_ci{ 194f08c3bdfSopenharmony_ci struct sigaction sa; 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_ci sa.sa_sigaction = handler; 197f08c3bdfSopenharmony_ci sa.sa_flags = flags; 198f08c3bdfSopenharmony_ci sigemptyset(&sa.sa_mask); 199f08c3bdfSopenharmony_ci sigaddset(&sa.sa_mask, sig_to_mask); 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ci TEST(sigaction(SIGUSR1, &sa, NULL)); 202f08c3bdfSopenharmony_ci if (TEST_RETURN != 0) { 203f08c3bdfSopenharmony_ci perror("sigaction"); 204f08c3bdfSopenharmony_ci tst_resm(TFAIL, "call failed unexpectedly"); 205f08c3bdfSopenharmony_ci return 1; 206f08c3bdfSopenharmony_ci } 207f08c3bdfSopenharmony_ci return 0; 208f08c3bdfSopenharmony_ci} 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci/* 211f08c3bdfSopenharmony_ci * setup() - performs all ONE TIME setup for this test. 212f08c3bdfSopenharmony_ci */ 213f08c3bdfSopenharmony_civoid setup(void) 214f08c3bdfSopenharmony_ci{ 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci TEST_PAUSE; 217f08c3bdfSopenharmony_ci} 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci/* 220f08c3bdfSopenharmony_ci * cleanup() - performs all ONE TIME cleanup for this test at 221f08c3bdfSopenharmony_ci * completion or premature exit. 222f08c3bdfSopenharmony_ci */ 223f08c3bdfSopenharmony_civoid cleanup(void) 224f08c3bdfSopenharmony_ci{ 225f08c3bdfSopenharmony_ci 226f08c3bdfSopenharmony_ci} 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ciint main(int ac, char **av) 229f08c3bdfSopenharmony_ci{ 230f08c3bdfSopenharmony_ci int lc; 231f08c3bdfSopenharmony_ci int i; 232f08c3bdfSopenharmony_ci int test_flags[] = { SA_RESETHAND | SA_SIGINFO, SA_RESETHAND, 233f08c3bdfSopenharmony_ci SA_RESETHAND | SA_SIGINFO, SA_RESETHAND | SA_SIGINFO 234f08c3bdfSopenharmony_ci }; 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci setup(); 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_ci /* reset tst_count in case we are looping */ 243f08c3bdfSopenharmony_ci tst_count = 0; 244f08c3bdfSopenharmony_ci 245f08c3bdfSopenharmony_ci testcase_no = 0; 246f08c3bdfSopenharmony_ci 247f08c3bdfSopenharmony_ci for (i = 0; i < TST_TOTAL; i++) { 248f08c3bdfSopenharmony_ci if (set_handler(test_flags[i], 0) == 0) { 249f08c3bdfSopenharmony_ci testcase_no++; 250f08c3bdfSopenharmony_ci switch (i) { 251f08c3bdfSopenharmony_ci case 0: 252f08c3bdfSopenharmony_ci /*FALLTHROUGH*/ case 1: 253f08c3bdfSopenharmony_ci (void)kill(getpid(), SIGUSR1); 254f08c3bdfSopenharmony_ci break; 255f08c3bdfSopenharmony_ci case 2: 256f08c3bdfSopenharmony_ci /*FALLTHROUGH*/ case 3: 257f08c3bdfSopenharmony_ci (void) 258f08c3bdfSopenharmony_ci pthread_kill(pthread_self(), 259f08c3bdfSopenharmony_ci SIGUSR1); 260f08c3bdfSopenharmony_ci break; 261f08c3bdfSopenharmony_ci default: 262f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, 263f08c3bdfSopenharmony_ci "illegal case number"); 264f08c3bdfSopenharmony_ci break; 265f08c3bdfSopenharmony_ci } 266f08c3bdfSopenharmony_ci } 267f08c3bdfSopenharmony_ci } 268f08c3bdfSopenharmony_ci } 269f08c3bdfSopenharmony_ci 270f08c3bdfSopenharmony_ci cleanup(); 271f08c3bdfSopenharmony_ci tst_exit(); 272f08c3bdfSopenharmony_ci} 273