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