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 * waitpid03.c 23 * 24 * DESCRIPTION 25 * Check that parent waits unitl specific child has returned. 26 * 27 * ALGORITHM 28 * Parent forks numerous (22 = MAXUPRC - 3) children, and starts waits : 29 * Should only wait for the specific child, a second wait on the same 30 * child should return with -1 and not one of the other zombied 31 * children. 32 * 33 * USAGE: <for command-line> 34 * waitpid03 [-c n] [-i n] [-I x] [-P x] [-t] 35 * where, -c n : Run n copies concurrently. 36 * -i n : Execute test n times. 37 * -I x : Execute test for x seconds. 38 * -P x : Pause for x seconds between iterations. 39 * -t : Turn on syscall timing. 40 * 41 * History 42 * 07/2001 John George 43 * -Ported 44 * 04/2002 wjhuie sigset cleanups 45 * 46 * Restrictions 47 * None 48 */ 49 50 #define DEBUG 0 51 52 #include <sys/types.h> 53 #include <signal.h> 54 #include <errno.h> 55 #include <sys/wait.h> 56 #include "test.h" 57 58 static void do_child(int); 59 static void setup(void); 60 static void cleanup(void); 61 62 char *TCID = "waitpid03"; 63 int TST_TOTAL = 1; 64 65 #define MAXUPRC 25 66 67 static int ikids; 68 static int pid[MAXUPRC]; 69 static int condition_number; 70 71 #ifdef UCLINUX 72 static void do_child_uclinux(void); 73 static int ikids_uclinux; 74 #endif 75 76 int main(int argc, char **argv) 77 { 78 int lc; 79 80 int status, ret; 81 82 tst_parse_opts(argc, argv, NULL, NULL); 83 #ifdef UCLINUX 84 maybe_run_child(&do_child, "d", &ikids_uclinux); 85 #endif 86 87 setup(); 88 89 /* check for looping state if -i option is given */ 90 for (lc = 0; TEST_LOOPING(lc); lc++) { 91 /* reset tst_count in case we are looping */ 92 tst_count = 0; 93 94 /* 95 * Set SIGTERM to SIG_DFL as test driver sets up to ignore 96 * SIGTERM 97 */ 98 if ((sig_t) signal(SIGTERM, SIG_DFL) == SIG_ERR) { 99 tst_resm(TFAIL, "Signal SIGTERM failed, errno = %d", 100 errno); 101 102 } 103 104 while (++ikids < MAXUPRC) { 105 pid[ikids] = FORK_OR_VFORK(); 106 if (pid[ikids] > 0) { 107 if (DEBUG) 108 tst_resm(TINFO, "child # %d", ikids); 109 } else if (pid[ikids] == -1) { 110 tst_brkm(TBROK|TERRNO, cleanup, "cannot open " 111 "fork #%d", ikids); 112 113 } else { 114 #ifdef UCLINUX 115 if (self_exec(argv[0], "d", ikids) < 0) { 116 tst_resm(TFAIL, "cannot self_exec #%d", 117 ikids); 118 } 119 #else 120 do_child(ikids); 121 #endif 122 } 123 } 124 125 for (ikids = 1; ikids < MAXUPRC; ikids++) { 126 if (DEBUG) 127 tst_resm(TINFO, "Killing #%d", ikids); 128 kill(pid[ikids], SIGTERM); 129 } 130 131 ikids = 0; 132 condition_number = 1; 133 134 /* Wait on one specific child */ 135 if (DEBUG) 136 tst_resm(TINFO, "Waiting for child:#%d", MAXUPRC / 2); 137 ret = waitpid(pid[MAXUPRC / 2], &status, 0); 138 if (ret != pid[MAXUPRC / 2]) { 139 tst_resm(TFAIL, "condition %d test failed. " 140 "waitpid(%d) returned %d.", 141 condition_number, pid[MAXUPRC / 2], ret); 142 } else { 143 tst_resm(TPASS, "Got correct child PID"); 144 } 145 condition_number++; 146 147 /* 148 * Child has already been waited on, waitpid should return 149 * -1 150 */ 151 ret = waitpid(pid[MAXUPRC / 2], &status, 0); 152 if (ret != -1) { 153 tst_resm(TFAIL, "condition %d test failed", 154 condition_number); 155 } else { 156 tst_resm(TPASS, "Condition %d test passed", 157 condition_number); 158 } 159 condition_number++; 160 } 161 162 cleanup(); 163 tst_exit(); 164 } 165 166 static void do_child(int ikids) 167 { 168 if (DEBUG) 169 tst_resm(TINFO, "child:%d", ikids); 170 pause(); 171 exit(0); 172 } 173 174 #ifdef UCLINUX 175 /* 176 * do_child_uclinux() 177 * run do_child with the appropriate ikids variable 178 */ 179 static void do_child_uclinux(void) 180 { 181 do_child(ikids_uclinux); 182 } 183 #endif 184 185 static void setup(void) 186 { 187 TEST_PAUSE; 188 } 189 190 static void cleanup(void) 191 { 192 while (ikids-- > 1) 193 kill(pid[ikids], SIGKILL); 194 } 195