waitpid05.c revision 2c58f605b021a69c199b2be2d65642d85fe631f1
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 65static void do_child(int); 66static void setup(void); 67static void cleanup(void); 68 69char *TCID = "waitpid05"; 70int TST_TOTAL = 1; 71 72#ifdef UCLINUX 73static void 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 msg = parse_opts(ac, av, NULL, NULL); 85 if (msg != NULL) 86 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 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) || (sig == 13) || 152 (sig == 14) || 153 (sig == 15)) { 154 tst_resm(TFAIL, 155 "signal " 156 "error : " 157 "core dump " 158 "bit set for" 159 " exception " 160 "number %d", 161 sig); 162 } 163 } else if ((sig == 3) || (sig == 4) || 164 (sig == 5) || (sig == 6) || 165 (sig == 8) || (sig == 11)) { 166 tst_resm(TFAIL, 167 "signal error: " 168 "core dump bit not " 169 "set for exception " 170 "number %d", sig); 171 } 172 173 /* 174 * nsig is the signal number returned 175 * by waitpid 176 */ 177 if (nsig != sig) { 178 tst_resm(TFAIL, "waitpid " 179 "error: unexpected " 180 "signal returned"); 181 tst_resm(TINFO, "got signal " 182 "%d, expected " 183 "%d", nsig, sig); 184 } 185 186 /* 187 * nexno is the exit number returned 188 * by waitpid 189 */ 190 nexno = status / 256; 191 if (nexno != 0) { 192 tst_resm(TFAIL, "signal " 193 "error: unexpected " 194 "exit number " 195 "returned"); 196 } else { 197 tst_resm(TPASS, "received " 198 "expected exit number."); 199 } 200 } 201 } 202 } 203 204 if (access("core", F_OK) == 0) 205 unlink("core"); 206 } 207 208 cleanup(); 209 tst_exit(); 210} 211 212static void do_child(int sig) 213{ 214 int exno = 1; 215 int pid = getpid(); 216 217 if (kill(pid, sig) == -1) { 218 tst_resm(TFAIL, "kill error: kill unsuccessful"); 219 exit(exno); 220 } 221} 222 223#ifdef UCLINUX 224/* 225 * do_child_uclinux() 226 * run do_child with the appropriate sig variable 227 */ 228static void do_child_uclinux(void) 229{ 230 do_child(sig_uclinux); 231} 232#endif 233 234static void setup(void) 235{ 236 struct rlimit newlimit; 237 238 TEST_PAUSE; 239 240 tst_tmpdir(); 241 242 newlimit.rlim_max = newlimit.rlim_cur = RLIM_INFINITY; 243 if (setrlimit(RLIMIT_CORE, &newlimit) != 0) 244 tst_resm(TWARN, 245 "setrlimit(RLIMIT_CORE,RLIM_INFINITY) failed; this may cause some false core-dump test failures"); 246} 247 248static void cleanup(void) 249{ 250 TEST_CLEANUP; 251 tst_rmdir(); 252} 253