waitpid05.c revision d17884d8c2207af1e8eca25ba16d475fa59c7a62
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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#include <usctest.h> 64 65void do_child(int); 66void setup(void); 67void cleanup(void); 68 69char *TCID = "waitpid05"; 70int TST_TOTAL = 1; 71extern int Tst_count; 72 73int flag; 74#define FAILED 1 75 76#ifdef UCLINUX 77void do_child_uclinux(void); 78static int sig_uclinux; 79#endif 80 81int main(int ac, char **av) 82{ 83 int pid, npid, sig, nsig; 84 int exno, nexno, status; 85 int lc; /* loop counter */ 86 char *msg; /* message returned from parse_opts */ 87 88 /* parse standard options */ 89 if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != 90 (char *) NULL) { 91 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 92 tst_exit(); 93 /*NOTREACHED*/ 94 } 95 96#ifdef UCLINUX 97 maybe_run_child(&do_child_uclinux, "d", &sig_uclinux); 98#endif 99 100 setup(); 101 102 /* check for looping state if -i option is given */ 103 for (lc = 0; TEST_LOOPING(lc); lc++) { 104 /* reset Tst_count in case we are looping */ 105 Tst_count = 0; 106 107 /* 108 * Set SIGTERM to SIG_DFL as test driver sets up to ignore 109 * SIGTERM 110 */ 111 if (signal(SIGTERM, SIG_DFL) == SIG_ERR) { 112 tst_resm(TFAIL, "Sigset SIGTERM failed, errno = %d", 113 errno); 114 tst_exit(); 115 } 116 117 exno = 1; 118 for (sig = 1; sig <= 15; sig++) { 119 if (sig == SIGUSR1 || sig == SIGUSR2 || sig == SIGBUS) { 120 continue; 121 } 122 /*Initialize signal to its default action*/ 123 signal(sig,SIG_DFL); 124 pid = FORK_OR_VFORK(); 125 126 if (pid == 0) { 127#ifdef UCLINUX 128 self_exec(av[0], "d", sig); 129 /* No fork() error check is done so don't */ 130 /* do an error check here */ 131#else 132 do_child(sig); 133#endif 134 } else { 135 errno = 0; 136 while (((npid = waitpid(pid, &status, 0)) != 137 -1) || (errno == EINTR)) { 138 if (errno == EINTR) { 139 continue; 140 } 141 if (npid != pid) { 142 tst_resm(TFAIL, "waitpid " 143 "error: unexpected " 144 "pid returned"); 145 } else { 146 tst_resm(TPASS, "received " 147 "expected pid."); 148 } 149 150 nsig = status % 256; 151 152 /* 153 * to check if the core dump bit has 154 * been set, bit #7 155 */ 156 if (nsig >= 128) { 157 nsig -= 128; 158 if ((sig == 1) || (sig == 2) || 159 (sig == 9) || 160 (sig == 13) || 161 (sig == 14) || 162 (sig == 15)) { 163 tst_resm(TFAIL, 164 "signal " 165 "error : " 166 "core dump " 167 "bit set for" 168 " exception " 169 "number %d", 170 sig); 171 } 172 } else if ((sig == 3) || (sig == 4) || 173 (sig == 5) || (sig == 6) || 174 (sig == 8) || (sig == 11)) { 175 tst_resm(TFAIL, 176 "signal error: " 177 "core dump bit not " 178 "set for exception " 179 "number %d", sig); 180 } 181 182 /* 183 * nsig is the signal number returned 184 * by waitpid 185 */ 186 if (nsig != sig) { 187 tst_resm(TFAIL, "waitpid " 188 "error: unexpected " 189 "signal returned"); 190 tst_resm(TINFO, "got signal " 191 "%d, expected " 192 "%d", nsig, sig); 193 } 194 195 /* 196 * nexno is the exit number returned 197 * by waitpid 198 */ 199 nexno = status / 256; 200 if (nexno != 0) { 201 tst_resm(TFAIL, "signal " 202 "error: unexpected " 203 "exit number " 204 "returned"); 205 } else { 206 tst_resm(TPASS, "received " 207 "expected exit number."); 208 } 209 } 210 } 211 } 212 213 if (access("core", F_OK) == 0) { 214 unlink("core"); 215 } 216 } 217 cleanup(); 218 /*NOTREACHED*/ 219 220 return(0); 221 222} 223 224/* 225 * do_child() 226 */ 227void 228do_child(int sig) 229{ 230 int exno = 1; 231 int pid = getpid(); 232 233 if (kill(pid, sig) == -1) { 234 tst_resm(TFAIL, "kill error: kill unsuccessful"); 235 exit(exno); 236 } 237} 238 239#ifdef UCLINUX 240/* 241 * do_child_uclinux() 242 * run do_child with the appropriate sig variable 243 */ 244void 245do_child_uclinux() 246{ 247 do_child(sig_uclinux); 248} 249#endif 250 251/* 252 * setup() 253 * performs all ONE TIME setup for this test 254 */ 255void 256setup(void) 257{ 258 struct rlimit newlimit; 259 260 /* Pause if that option was specified 261 * TEST_PAUSE contains the code to fork the test with the -c option. 262 * You want to make sure you do this before you create your temporary 263 * directory. 264 */ 265 TEST_PAUSE; 266 267 /* Create a unique temporary directory and chdir() to it. */ 268 tst_tmpdir(); 269 270 newlimit.rlim_max = newlimit.rlim_cur = RLIM_INFINITY; 271 if (setrlimit(RLIMIT_CORE, &newlimit) != 0) 272 tst_resm(TWARN, "setrlimit(RLIMIT_CORE,RLIM_INFINITY) failed; this may cause some false core-dump test failures"); 273} 274 275/* 276 * cleanup() 277 * performs all ONE TIME cleanup for this test at 278 * completion or premature exit 279 */ 280void 281cleanup(void) 282{ 283 /* 284 * print timing stats if that option was specified. 285 * print errno log if that option was specified. 286 */ 287 TEST_CLEANUP; 288 289 tst_rmdir(); 290 291 /* exit with return code appropriate for results */ 292 tst_exit(); 293 /*NOTREACHED*/ 294} 295