blob: a692c62479f26f147bf253afec55c7efec48e5de [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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
22 * waitpid12.c
subrata_modakbdbaec52009-02-26 12:14:51 +000023 *
plars865695b2001-08-27 22:15:12 +000024 * DESCRIPTION
25 * Tests to see if pid's returned from fork and waitpid are same
subrata_modakbdbaec52009-02-26 12:14:51 +000026 *
plars865695b2001-08-27 22:15:12 +000027 * ALGORITHM
Wanlong Gaoae24b142012-11-20 10:32:33 +080028 * Check proper functioning of waitpid with pid = -1 and arg = WNOHANG
plars865695b2001-08-27 22:15:12 +000029 *
30 * USAGE: <for command-line>
31 * waitpid12 [-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
robbiew112db7a2002-04-25 15:57:02 +000038 * 04/2002 wjhuie sigset testx for SIG_ERR not < 0, TPASS|TFAIL issued
robbiew4644c7e2002-04-26 14:33:32 +000039 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000040 *
41 * Restrictions
Wanlong Gaoae24b142012-11-20 10:32:33 +080042 * None
plars865695b2001-08-27 22:15:12 +000043 */
44
45#include <sys/types.h>
46#include <signal.h>
47#include <errno.h>
48#include <sys/wait.h>
Garrett Coopere8530df2010-12-21 11:37:57 -080049#include "test.h"
plars865695b2001-08-27 22:15:12 +000050
51#define MAXKIDS 8
52
53char *TCID = "waitpid12";
54int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000055
robbiew3d5c7352003-01-13 17:49:51 +000056volatile int intintr;
Wanlong Gaoae24b142012-11-20 10:32:33 +080057static void setup(void);
58static void cleanup(void);
59static void inthandlr();
60static void wait_for_parent(void);
61static void do_exit(void);
62static void setup_sigint(void);
robbiewd34d5812005-07-11 22:28:09 +000063#ifdef UCLINUX
Wanlong Gaoae24b142012-11-20 10:32:33 +080064static void do_exit_uclinux(void);
robbiewd34d5812005-07-11 22:28:09 +000065#endif
plars865695b2001-08-27 22:15:12 +000066
Wanlong Gaoae24b142012-11-20 10:32:33 +080067static int fail;
plars865695b2001-08-27 22:15:12 +000068
plars74948ad2002-11-14 16:16:14 +000069int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000070{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020071 const char *msg;
plars865695b2001-08-27 22:15:12 +000072
73 int kid_count, ret_val, status;
plars74948ad2002-11-14 16:16:14 +000074 int i, j, k, found;
plars865695b2001-08-27 22:15:12 +000075 int group1, group2;
76 int fork_kid_pid[MAXKIDS], wait_kid_pid[MAXKIDS];
77 int pid;
78
Wanlong Gaoae24b142012-11-20 10:32:33 +080079 msg = parse_opts(argc, argv, NULL, NULL);
80 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000081 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080082
robbiewd34d5812005-07-11 22:28:09 +000083#ifdef UCLINUX
84 maybe_run_child(&do_exit_uclinux, "");
85#endif
86
plars865695b2001-08-27 22:15:12 +000087 setup();
88
Caspar Zhangd59a6592013-03-07 14:59:12 +080089 tst_count = 0;
Garrett Cooperc548a312011-03-04 02:12:05 -080090 fail = 0;
plars865695b2001-08-27 22:15:12 +000091
Garrett Cooperc548a312011-03-04 02:12:05 -080092 /*
93 * Need to have test run from child as test driver causes
94 * test to be a session leader and setpgrp fails.
95 */
plars865695b2001-08-27 22:15:12 +000096
Wanlong Gaoae24b142012-11-20 10:32:33 +080097 pid = FORK_OR_VFORK();
98 if (pid > 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -080099 waitpid(pid, &status, 0);
100 if (WEXITSTATUS(status) != 0) {
101 tst_resm(TFAIL, "child returned bad status");
102 fail = 1;
103 }
104 if (fail)
105 tst_resm(TFAIL, "%s FAILED", TCID);
106 else
107 tst_resm(TPASS, "%s PASSED", TCID);
108 cleanup();
109 tst_exit();
Wanlong Gaoae24b142012-11-20 10:32:33 +0800110 } else if (pid < 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800111 tst_brkm(TBROK, cleanup, "fork failed");
Wanlong Gaoae24b142012-11-20 10:32:33 +0800112 }
plars865695b2001-08-27 22:15:12 +0000113
Garrett Cooperc548a312011-03-04 02:12:05 -0800114 /*
115 * Set up to catch SIGINT. The kids will wait till a SIGINT
116 * has been received before they proceed.
117 */
118 setup_sigint();
plars865695b2001-08-27 22:15:12 +0000119
Garrett Cooperc548a312011-03-04 02:12:05 -0800120 group1 = getpgrp();
plars865695b2001-08-27 22:15:12 +0000121
Garrett Cooperc548a312011-03-04 02:12:05 -0800122 for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
123 if (kid_count == (MAXKIDS / 2))
124 group2 = setpgrp();
plars865695b2001-08-27 22:15:12 +0000125
Garrett Cooperc548a312011-03-04 02:12:05 -0800126 intintr = 0;
127 ret_val = FORK_OR_VFORK();
128 if (ret_val == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000129#ifdef UCLINUX
Garrett Cooperc548a312011-03-04 02:12:05 -0800130 if (self_exec(argv[0], "") < 0)
131 tst_resm(TFAIL, "self_exec kid %d "
132 "failed", kid_count);
robbiewd34d5812005-07-11 22:28:09 +0000133#else
Garrett Cooperc548a312011-03-04 02:12:05 -0800134 do_exit();
robbiewd34d5812005-07-11 22:28:09 +0000135#endif
plars865695b2001-08-27 22:15:12 +0000136 }
137
Garrett Cooperc548a312011-03-04 02:12:05 -0800138 if (ret_val < 0)
Wanlong Gaoae24b142012-11-20 10:32:33 +0800139 tst_resm(TFAIL | TERRNO, "forking kid %d failed",
140 kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800141
142 /* parent */
143 fork_kid_pid[kid_count] = ret_val;
144 }
145
146 /* Check that waitpid with WNOHANG returns zero */
Wanlong Gaoae24b142012-11-20 10:32:33 +0800147 ret_val = waitpid(0, &status, WNOHANG);
148 if (ret_val != 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800149 tst_resm(TFAIL, "Waitpid returned wrong value");
150 tst_resm(TFAIL, "Expected 0 got %d", ret_val);
151 fail = 1;
152 }
robbiewd34d5812005-07-11 22:28:09 +0000153#ifdef UCLINUX
Garrett Cooperc548a312011-03-04 02:12:05 -0800154 /* Give the kids a chance to setup SIGINT again, since this is
155 * cleared by exec().
156 */
157 sleep(3);
robbiewd34d5812005-07-11 22:28:09 +0000158#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000159
Garrett Cooperc548a312011-03-04 02:12:05 -0800160 /* Now send all the kids a SIGINT to tell them to proceed */
161 for (i = 0; i < MAXKIDS; i++)
162 if (kill(fork_kid_pid[i], SIGINT) < 0)
Wanlong Gaoae24b142012-11-20 10:32:33 +0800163 tst_resm(TFAIL | TERRNO, "killing child %d failed", i);
Garrett Cooper2c282152010-12-16 00:55:50 -0800164
Garrett Cooperc548a312011-03-04 02:12:05 -0800165 /*
166 * Wait till all kids have terminated. Stash away their
167 * pid's in an array.
168 */
169 kid_count = 0;
170 errno = 0;
171 sleep(2);
172 while (((ret_val = waitpid(0, &status, WNOHANG)) != -1) ||
173 (errno == EINTR)) {
174 if ((ret_val == -1) || (ret_val == 0))
175 continue;
plars865695b2001-08-27 22:15:12 +0000176
Garrett Cooperc548a312011-03-04 02:12:05 -0800177 if (!WIFEXITED(status)) {
178 tst_resm(TFAIL, "Child %d did not exit "
179 "normally", ret_val);
plars865695b2001-08-27 22:15:12 +0000180 fail = 1;
plars865695b2001-08-27 22:15:12 +0000181 } else {
Garrett Cooperc548a312011-03-04 02:12:05 -0800182 if (WEXITSTATUS(status) != 3) {
183 tst_resm(TFAIL, "Child %d exited with "
184 "wrong status", ret_val);
185 tst_resm(TFAIL, "Expected 3 got %d",
186 WEXITSTATUS(status));
187 fail = 1;
188 }
189 }
190 wait_kid_pid[kid_count++] = ret_val;
191 }
192
193 /*
194 * Check that for every entry in the fork_kid_pid array,
195 * there is a matching pid in the wait_kid_pid array. If
196 * not, it's an error.
197 */
198 for (i = 0; i < kid_count; i++) {
199 found = 0;
200 for (j = (MAXKIDS / 2); j < MAXKIDS; j++) {
201 if (fork_kid_pid[j] == wait_kid_pid[i]) {
202 found = 1;
203 break;
204 }
205 }
206 if (!found) {
207 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gaoae24b142012-11-20 10:32:33 +0800208 "for the fork_kid_pid of %d", wait_kid_pid[i]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800209 for (k = 0; k < MAXKIDS; k++)
210 tst_resm(TFAIL, "fork_kid_pid[%d] = "
211 "%d", k, fork_kid_pid[k]);
212 for (k = 0; k < kid_count; k++)
213 tst_resm(TFAIL, "wait_kid_pid[%d] = "
214 "%d", k, wait_kid_pid[k]);
215 fail = 1;
plars865695b2001-08-27 22:15:12 +0000216 }
217 }
robbiewaa01abd2003-03-27 18:39:24 +0000218
Garrett Cooperc548a312011-03-04 02:12:05 -0800219 if (kid_count != (MAXKIDS / 2)) {
220 tst_resm(TFAIL, "Wrong number of children waited on "
221 "for pid = 0");
222 tst_resm(TFAIL, "Expected 4 got %d", kid_count);
223 fail = 1;
224 }
225
226 /* Make sure can pickup children in a diff. process group */
227
228 kid_count = 0;
229 errno = 0;
230 while (((ret_val = waitpid(-(group1), &status, WNOHANG)) !=
231 -1) || (errno == EINTR)) {
Wanlong Gaoae24b142012-11-20 10:32:33 +0800232 if (ret_val == -1 || ret_val == 0)
Garrett Cooperc548a312011-03-04 02:12:05 -0800233 continue;
Wanlong Gaoae24b142012-11-20 10:32:33 +0800234
Garrett Cooperc548a312011-03-04 02:12:05 -0800235 if (!WIFEXITED(status)) {
236 tst_resm(TFAIL, "Child %d did not exit "
237 "normally", ret_val);
238 fail = 1;
239 } else {
240 if (WEXITSTATUS(status) != 3) {
241 tst_resm(TFAIL, "Child %d exited with "
242 "wrong status", ret_val);
243 tst_resm(TFAIL, "Expected 3 got %d",
244 WEXITSTATUS(status));
245 fail = 1;
246 }
247 }
248 wait_kid_pid[kid_count++] = ret_val;
249 }
250
251 /*
252 * Check that for every entry in the fork_kid_pid array,
253 * there is a matching pid in the wait_kid_pid array. If
254 * not, it's an error.
255 */
256 for (i = 0; i < kid_count; i++) {
257 found = 0;
258 for (j = 0; j < (MAXKIDS / 2); j++) {
259 if (fork_kid_pid[j] == wait_kid_pid[i]) {
260 found = 1;
261 break;
262 }
263 }
264 if (!found) {
265 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gaoae24b142012-11-20 10:32:33 +0800266 "for the fork_kid_pid of %d", fork_kid_pid[j]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800267 for (k = 0; k < MAXKIDS; k++)
268 tst_resm(TFAIL, "fork_kid_pid[%d] = "
269 "%d", k, fork_kid_pid[k]);
270 for (k = 0; k < kid_count; k++)
271 tst_resm(TFAIL, "wait_kid_pid[%d] = "
272 "%d", k, wait_kid_pid[k]);
273 fail = 1;
274 }
275 }
276 if (kid_count != (MAXKIDS / 2)) {
277 tst_resm(TFAIL, "Wrong number of children waited on "
278 "for pid = 0");
279 tst_resm(TFAIL, "Expected 4 got %d", kid_count);
280 fail = 1;
281 }
282
283 if (fail)
284 tst_resm(TFAIL, "Test FAILED");
285 else
286 tst_resm(TPASS, "Test PASSED");
287
288 tst_exit();
plars865695b2001-08-27 22:15:12 +0000289}
290
Wanlong Gaoae24b142012-11-20 10:32:33 +0800291static void setup_sigint(void)
robbiewd34d5812005-07-11 22:28:09 +0000292{
Garrett Cooperc548a312011-03-04 02:12:05 -0800293 if (signal(SIGINT, inthandlr) == SIG_ERR)
Wanlong Gaoae24b142012-11-20 10:32:33 +0800294 tst_brkm(TFAIL | TERRNO, NULL, "signal SIGINT failed");
robbiewd34d5812005-07-11 22:28:09 +0000295}
296
Wanlong Gaoae24b142012-11-20 10:32:33 +0800297static void setup(void)
plars865695b2001-08-27 22:15:12 +0000298{
plars865695b2001-08-27 22:15:12 +0000299 tst_sig(FORK, DEF_HANDLER, cleanup);
300
plars865695b2001-08-27 22:15:12 +0000301 TEST_PAUSE;
302}
303
Wanlong Gaoae24b142012-11-20 10:32:33 +0800304static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000305{
Garrett Cooperc548a312011-03-04 02:12:05 -0800306}
plars865695b2001-08-27 22:15:12 +0000307
Mike Frysingerc57fba52014-04-09 18:56:30 -0400308static void inthandlr(void)
plars865695b2001-08-27 22:15:12 +0000309{
310 intintr++;
311}
312
Wanlong Gaoae24b142012-11-20 10:32:33 +0800313static void wait_for_parent(void)
plars865695b2001-08-27 22:15:12 +0000314{
315 int testvar;
316
Garrett Cooperc548a312011-03-04 02:12:05 -0800317 while (!intintr)
plars865695b2001-08-27 22:15:12 +0000318 testvar = 0;
plars865695b2001-08-27 22:15:12 +0000319}
320
Wanlong Gaoae24b142012-11-20 10:32:33 +0800321static void do_exit(void)
plars865695b2001-08-27 22:15:12 +0000322{
323 wait_for_parent();
324 exit(3);
325}
robbiewd34d5812005-07-11 22:28:09 +0000326
327#ifdef UCLINUX
Wanlong Gaoae24b142012-11-20 10:32:33 +0800328static void do_exit_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000329{
330 setup_sigint();
331 do_exit();
332}
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800333#endif