blob: 1625f16b9dd492a4b3ad3776d1d4039d48eb5b8b [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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 * waitpid11.c
23 *
24 * DESCRIPTION
25 * Tests to see if pid's returned from fork and waitpid are same
26 *
27 * ALGORITHM
28 * Check proper functioning of waitpid with pid = -1 and arg = 0
29 *
30 * USAGE: <for command-line>
31 * waitpid11 [-c n] [-t]
32 * where, -c n : Run n copies concurrently.
33 * -t : Turn on syscall timing.
34 *
35 * History
36 * 07/2001 John George
37 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000038 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000039 *
40 * Restrictions
41 * None
42 */
43
44#include <sys/types.h>
45#include <signal.h>
46#include <errno.h>
47#include <sys/wait.h>
48#include <test.h>
49#include <usctest.h>
50
51#define MAXKIDS 8
52
53char *TCID = "waitpid11";
54int TST_TOTAL = 1;
55extern int Tst_count;
56
57int intintr;
58void setup(void);
59void cleanup(void);
60void inthandlr();
61int wait_for_parent();
62int do_exit();
63
64int fail;
65
plarsac85d1c2002-06-10 14:52:37 +000066int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000067{
68 int lc; /* loop counter */
69 char *msg; /* message returned from parse_opts */
70
71 int kid_count, ret_val, status;
72 int i, j, k, found, iterations;
73 int group1, group2;
74 int fork_kid_pid[MAXKIDS], wait_kid_pid[MAXKIDS];
75 int pid;
76
77 /* parse standard options */
78 if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) !=
79 (char *)NULL) {
80 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
81 tst_exit();
82 /*NOTREACHED*/
83 }
84
85 setup();
86
87 /* check for looping state if -i option is given */
88 for (lc = 0; TEST_LOOPING(lc); lc++) {
89
90 /* reset Tst_count in case we are looping */
91 Tst_count = 0;
92
93 /*
94 * Need to have test run from child as test driver causes
95 * test to be a session leader and setpgrp fails.
96 */
97
98 if (pid = fork()) {
99 fail = 0;
100 waitpid(pid, &status, 0);
101 if (WEXITSTATUS(status) != 0) {
102 tst_resm(TFAIL, "child returned bad status");
103 fail = 1;
104 }
105 if (fail) {
106 tst_resm(TINFO, "%s FAILED", TCID);
107 } else {
108 tst_resm(TINFO, "%s PASSED", TCID);
109 }
110 cleanup();
111 /*NOTREACHED*/
112 } else if (pid < 0 ) {
113 tst_brkm(TBROK, cleanup, "fork failed");
114 /*NOTREACHED*/
115 }
116
117 /*
118 * Set up to catch SIGINT. The kids will wait till a SIGINT
119 * has been received before they proceed.
120 */
plarsac85d1c2002-06-10 14:52:37 +0000121 if ((sig_t)signal(SIGINT, inthandlr) == SIG_ERR) {
robbiew4644c7e2002-04-26 14:33:32 +0000122 tst_resm(TFAIL, "signal SIGINT failed, errno = %d",
plars865695b2001-08-27 22:15:12 +0000123 errno);
124 tst_exit();
125 /*NOTREACHED*/
126 }
127
128 group1 = getpgrp();
129
130 for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
131 if (kid_count == (MAXKIDS / 2)) {
132 group2 = setpgrp();
133 }
134
135 intintr = 0;
136 ret_val = fork();
137 if (ret_val == 0) {
138 do_exit();
139 /*NOTREACHED*/
140 }
141
142 if (ret_val < 0) {
143 tst_resm(TFAIL, "Fork kid %d failed. errno = "
144 "%d", kid_count, errno);
145 tst_exit();
146 /*NOTREACHED*/
147 }
148
149 /* parent */
150 fork_kid_pid[kid_count] = ret_val;
151 }
152
153 /* Now send all the kids a SIGINT to tell them to proceed */
154 for (i = 0; i < MAXKIDS; i++) {
155 if (kill(fork_kid_pid[i], SIGINT) < 0) {
156 tst_resm(TFAIL, "Kill of child %d failed, "
157 "errno = %d", i, errno);
158 tst_exit();
159 /*NOTREACHED*/
160 }
161 }
162
163 /*
164 * Wait till all kids have terminated. Stash away their
165 * pid's in an array.
166 */
167 kid_count = 0;
168 errno = 0;
169 while (((ret_val = waitpid(0, &status, 0)) != -1) ||
170 (errno == EINTR)) {
171 if (ret_val == -1) {
172 continue;
173 }
174
175 if (!WIFEXITED(status)) {
176 tst_resm(TFAIL, "Child %d did not exit "
177 "normally", ret_val);
178 fail = 1;
179 } else {
180 if (WEXITSTATUS(status) != 3) {
181 tst_resm(TFAIL, "Child %d exited with "
182 "wrong status", ret_val);
183 tst_resm(TFAIL, "Expected 3 got %d",
184 WEXITSTATUS(status));
185 fail = 1;
186 }
187 }
188 wait_kid_pid[kid_count++] = ret_val;
189 }
190
191 /*
192 * Check that for every entry in the fork_kid_pid array,
193 * there is a matching pid in the wait_kid_pid array. If
194 * not, it's an error.
195 */
196 for (i = 0; i < kid_count; i++) {
197 found = 0;
198 for (j = (MAXKIDS / 2); j < MAXKIDS; j++) {
199 if (fork_kid_pid[j] == wait_kid_pid[i]) {
200 found = 1;
201 break;
202 }
203 }
204 if (!found) {
205 tst_resm(TFAIL, "Did not find a wait_kid_pid "
206 "for the fork_kid_pid of %d",
207 fork_kid_pid[j]);
208 for (k = 0; k < MAXKIDS; k++) {
209 tst_resm(TFAIL, "fork_kid_pid[%d] = "
210 "%d", k, fork_kid_pid[k]);
211 }
212 for (k = 0; k < kid_count; k++) {
213 tst_resm(TFAIL, "wait_kid_pid[%d] = "
214 "%d", k, wait_kid_pid[k]);
215 }
216 fail = 1;
217 }
218 }
219
220 if (kid_count != (MAXKIDS / 2)) {
221 tst_resm(TFAIL, "Wrong number of children waited on "
222 "for pid = 0");
223 tst_resm(TFAIL, "Expected 4 got %d", kid_count);
224 fail = 1;
225 }
226
227 /* Make sure can pickup children in a diff. process group */
228
229 kid_count = 0;
230 errno = 0;
231 while (((ret_val = waitpid(-(group1), &status, 0)) != -1) ||
232 (errno == EINTR)) {
233 if (ret_val == -1) {
234 continue;
235 }
236 if (!WIFEXITED(status)) {
237 tst_resm(TFAIL, "Child %d did not exit "
238 "normally", ret_val);
239 fail = 1;
240 } else {
241 if (WEXITSTATUS(status) != 3) {
242 tst_resm(TFAIL, "Child %d exited with "
243 "wrong status", ret_val);
244 tst_resm(TFAIL, "Expected 3 got %d",
245 WEXITSTATUS(status));
246 fail = 1;
247 }
248 }
249 wait_kid_pid[kid_count++] = ret_val;
250 }
251
252 /*
253 * Check that for every entry in the fork_kid_pid array,
254 * there is a matching pid in the wait_kid_pid array. If
255 * not, it's an error.
256 */
257 for (i = 0; i < kid_count; i++) {
258 found = 0;
259 for (j = 0; j < (MAXKIDS / 2); j++) {
260 if (fork_kid_pid[j] == wait_kid_pid[i]) {
261 found = 1;
262 break;
263 }
264 }
265 if (!found) {
266 tst_resm(TFAIL, "Did not find a wait_kid_pid "
267 "for the fork_kid_pid of %d",
268 fork_kid_pid[j]);
269 for (k = 0; k < MAXKIDS; k++) {
270 tst_resm(TFAIL, "fork_kid_pid[%d] = "
271 "%d", k, fork_kid_pid[k]);
272 }
273 for (k = 0; k < kid_count; k++) {
274 tst_resm(TFAIL, "wait_kid_pid[%d] = "
275 "%d", k, wait_kid_pid[k]);
276 }
277 fail = 1;
278 }
279 }
280 if (kid_count != (MAXKIDS / 2)) {
281 tst_resm(TFAIL, "Wrong number of children waited on "
282 "for pid = 0");
283 tst_resm(TFAIL, "Expected 4 got %d");
284 fail = 1;
285 }
286
287 if (fail) {
288 tst_resm(TINFO, "Test FAILED");
289 exit(1);
290 } else {
291 tst_resm(TINFO, "Test PASSED");
292 exit(0);
293 }
294 }
295}
296
297/*
298 * setup()
299 * performs all ONE TIME setup for this test
300 */
301void
302setup(void)
303{
304 /* Pause if that option was specified
305 * TEST_PAUSE contains the code to fork the test with the -c option.
306 */
307 TEST_PAUSE;
308}
309
310/*
311 * cleanup()
312 * performs all ONE TIME cleanup for this test at
313 * completion or premature exit
314 */
315void
316cleanup(void)
317{
318 /*
319 * print timing stats if that option was specified.
320 * print errno log if that option was specified.
321 */
322 TEST_CLEANUP;
323
324 /* exit with return code appropriate for results */
325 tst_exit();
326 /*NOTREACHED*/
327}
328void
329inthandlr()
330{
331 intintr++;
332}
333
334int
335wait_for_parent()
336{
337 int testvar;
338
339 while (!intintr) {
340 testvar = 0;
341 }
342}
343
344int
345do_exit()
346{
347 wait_for_parent();
348 exit(3);
349}