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