1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * NAME 22 * waitpid05.c 23 * 24 * DESCRIPTION 25 * Check that when a child kills itself with a kill statement after 26 * determining its process id by using getpid, the parent receives a 27 * correct report of the cause of its death. This also indirectly 28 * checks that getpid returns the correct process id. 29 * 30 * ALGORITHM 31 * For signals 1 - 15: fork a child that determines it's own process 32 * id, then sends the signal to itself. The parent waits to see if the 33 * demise of the child results in the signal number being returned to 34 * the parent. 35 * 36 * USAGE: <for command-line> 37 * waitpid05 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 38 * where, -c n : Run n copies concurrently. 39 * -e : Turn on errno logging. 40 * -i n : Execute test n times. 41 * -I x : Execute test for x seconds. 42 * -P x : Pause for x seconds between iterations. 43 * -t : Turn on syscall timing. 44 * 45 * History 46 * 07/2001 John George 47 * -Ported 48 * 04/2002 wjhuie sigset cleanups 49 * 50 * Restrictions 51 * None 52 */ 53 54 #include <sys/file.h> 55 #include <sys/signal.h> 56 #include <sys/types.h> 57 #include <sys/wait.h> 58 #include <sys/time.h> 59 #include <sys/resource.h> 60 #include <unistd.h> 61 #include <errno.h> 62 #include "test.h" 63 64 static void do_child(int); 65 static void setup(void); 66 static void cleanup(void); 67 68 char *TCID = "waitpid05"; 69 int TST_TOTAL = 1; 70 71 #ifdef UCLINUX 72 static void do_child_uclinux(void); 73 static int sig_uclinux; 74 #endif 75 76 int main(int ac, char **av) 77 { 78 int pid, npid, sig, nsig; 79 int exno, nexno, status; 80 int lc; 81 82 tst_parse_opts(ac, av, NULL, NULL); 83 84 #ifdef UCLINUX 85 maybe_run_child(&do_child_uclinux, "d", &sig_uclinux); 86 #endif 87 88 setup(); 89 90 /* check for looping state if -i option is given */ 91 for (lc = 0; TEST_LOOPING(lc); lc++) { 92 /* reset tst_count in case we are looping */ 93 tst_count = 0; 94 95 /* 96 * Set SIGTERM to SIG_DFL as test driver sets up to ignore 97 * SIGTERM 98 */ 99 if (signal(SIGTERM, SIG_DFL) == SIG_ERR) { 100 tst_resm(TFAIL, "Sigset SIGTERM failed, errno = %d", 101 errno); 102 103 } 104 105 exno = 1; 106 for (sig = 1; sig <= 15; sig++) { 107 if (sig == SIGUSR1 || sig == SIGUSR2 || sig == SIGBUS) 108 continue; 109 110 /*Initialize signal to its default action */ 111 signal(sig, SIG_DFL); 112 pid = FORK_OR_VFORK(); 113 114 if (pid == 0) { 115 #ifdef UCLINUX 116 self_exec(av[0], "d", sig); 117 /* No fork() error check is done so don't */ 118 /* do an error check here */ 119 #else 120 do_child(sig); 121 #endif 122 } else { 123 errno = 0; 124 while (((npid = waitpid(pid, &status, 0)) != 125 -1) || (errno == EINTR)) { 126 if (errno == EINTR) 127 continue; 128 129 if (npid != pid) { 130 tst_resm(TFAIL, "waitpid " 131 "error: unexpected " 132 "pid returned"); 133 } else { 134 tst_resm(TPASS, "received " 135 "expected pid."); 136 } 137 138 nsig = status % 256; 139 140 /* 141 * to check if the core dump bit has 142 * been set, bit #7 143 */ 144 if (nsig >= 128) { 145 nsig -= 128; 146 if ((sig == 1) || (sig == 2) || 147 (sig == 9) || (sig == 13) || 148 (sig == 14) || 149 (sig == 15)) { 150 tst_resm(TFAIL, 151 "signal " 152 "error : " 153 "core dump " 154 "bit set for" 155 " exception " 156 "number %d", 157 sig); 158 } 159 } else if ((sig == 3) || (sig == 4) || 160 (sig == 5) || (sig == 6) || 161 (sig == 8) || (sig == 11)) { 162 tst_resm(TFAIL, 163 "signal error: " 164 "core dump bit not " 165 "set for exception " 166 "number %d", sig); 167 } 168 169 /* 170 * nsig is the signal number returned 171 * by waitpid 172 */ 173 if (nsig != sig) { 174 tst_resm(TFAIL, "waitpid " 175 "error: unexpected " 176 "signal returned"); 177 tst_resm(TINFO, "got signal " 178 "%d, expected " 179 "%d", nsig, sig); 180 } 181 182 /* 183 * nexno is the exit number returned 184 * by waitpid 185 */ 186 nexno = status / 256; 187 if (nexno != 0) { 188 tst_resm(TFAIL, "signal " 189 "error: unexpected " 190 "exit number " 191 "returned"); 192 } else { 193 tst_resm(TPASS, "received " 194 "expected exit number."); 195 } 196 } 197 } 198 } 199 200 if (access("core", F_OK) == 0) 201 unlink("core"); 202 } 203 204 cleanup(); 205 tst_exit(); 206 } 207 208 static void do_child(int sig) 209 { 210 int exno = 1; 211 int pid = getpid(); 212 213 if (kill(pid, sig) == -1) { 214 tst_resm(TFAIL, "kill error: kill unsuccessful"); 215 exit(exno); 216 } 217 } 218 219 #ifdef UCLINUX 220 /* 221 * do_child_uclinux() 222 * run do_child with the appropriate sig variable 223 */ 224 static void do_child_uclinux(void) 225 { 226 do_child(sig_uclinux); 227 } 228 #endif 229 230 static void setup(void) 231 { 232 struct rlimit newlimit; 233 234 TEST_PAUSE; 235 236 tst_tmpdir(); 237 238 newlimit.rlim_max = newlimit.rlim_cur = RLIM_INFINITY; 239 if (setrlimit(RLIMIT_CORE, &newlimit) != 0) 240 tst_resm(TWARN, 241 "setrlimit(RLIMIT_CORE,RLIM_INFINITY) failed; this may cause some false core-dump test failures"); 242 } 243 244 static void cleanup(void) 245 { 246 tst_rmdir(); 247 } 248