blob: f161bc86124a56cc8b9d621412facc55666f4d78 [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 * waitpid13.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 Gao04cfe1b2012-11-20 10:32:33 +080028 * Check proper functioning of waitpid with pid = 0 and < -1 with arg
29 * WUNTRACED
plars865695b2001-08-27 22:15:12 +000030 *
31 * USAGE: <for command-line>
32 * waitpid13 [-c n] [-t]
33 * where, -c n : Run n copies concurrently.
34 * -t : Turn on syscall timing.
35 *
36 * History
37 * 07/2001 John George
38 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000039 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000040 *
41 * Restrictions
Wanlong Gao04cfe1b2012-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 = "waitpid13";
54int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000055
robbiew3d5c7352003-01-13 17:49:51 +000056volatile int intintr;
Wanlong Gao04cfe1b2012-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 Gao04cfe1b2012-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 Gao04cfe1b2012-11-20 10:32:33 +080067static int fail;
plars865695b2001-08-27 22:15:12 +000068
plarsac85d1c2002-06-10 14:52:37 +000069int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000070{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020071 const char *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +000072
plars74948ad2002-11-14 16:16:14 +000073 int kid_count, ret_val, status;
74 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 Gao04cfe1b2012-11-20 10:32:33 +080079 msg = parse_opts(ac, av, NULL, NULL);
80 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000081 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Wanlong Gao04cfe1b2012-11-20 10:32:33 +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 */
Wanlong Gao04cfe1b2012-11-20 10:32:33 +080096 pid = FORK_OR_VFORK();
97 if (pid > 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -080098 waitpid(pid, &status, 0);
99 if (WEXITSTATUS(status) != 0) {
100 tst_resm(TFAIL, "child returned bad status");
101 fail = 1;
102 }
103 if (fail)
104 tst_resm(TFAIL, "%s FAILED", TCID);
105 else
106 tst_resm(TPASS, "%s PASSED", TCID);
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800107
Garrett Cooperc548a312011-03-04 02:12:05 -0800108 cleanup();
109 tst_exit();
Wanlong Gao04cfe1b2012-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 Gao04cfe1b2012-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(av[0], "") < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800131 tst_resm(TFAIL | TERRNO, "self_exec kid %d "
Garrett Cooperc548a312011-03-04 02:12:05 -0800132 "failed", kid_count);
Garrett Cooper2c282152010-12-16 00:55:50 -0800133
Garrett Cooperc548a312011-03-04 02:12:05 -0800134 }
robbiewd34d5812005-07-11 22:28:09 +0000135#else
Garrett Cooperc548a312011-03-04 02:12:05 -0800136 do_exit();
robbiewd34d5812005-07-11 22:28:09 +0000137#endif
plars865695b2001-08-27 22:15:12 +0000138 }
139
Garrett Cooperc548a312011-03-04 02:12:05 -0800140 if (ret_val < 0)
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800141 tst_resm(TFAIL | TERRNO, "forking kid %d failed",
142 kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800143
144 /* parent */
145 fork_kid_pid[kid_count] = ret_val;
146 }
147
148 /* Check that waitpid with WNOHANG|WUNTRACED returns zero */
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800149 ret_val = waitpid(0, &status, WNOHANG | WUNTRACED);
150 if (ret_val != 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800151 tst_resm(TFAIL, "Waitpid returned wrong value"
152 "from waitpid(WNOHANG|WUNTRACED)");
153 tst_resm(TFAIL, "Expected 0 got %d", ret_val);
154 fail = 1;
155 }
robbiewd34d5812005-07-11 22:28:09 +0000156#ifdef UCLINUX
Garrett Cooperc548a312011-03-04 02:12:05 -0800157 /* Give the kids a chance to setup SIGINT again, since this is
158 * cleared by exec().
159 */
160 sleep(3);
robbiewd34d5812005-07-11 22:28:09 +0000161#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000162
Garrett Cooperc548a312011-03-04 02:12:05 -0800163 /* Now send all the kids a SIGINT to tell them to proceed */
164 for (i = 0; i < MAXKIDS; i++) {
165 if (kill(fork_kid_pid[i], SIGINT) < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800166 tst_resm(TFAIL | TERRNO, "killing child %d failed", i);
plars865695b2001-08-27 22:15:12 +0000167 fail = 1;
168 }
plars865695b2001-08-27 22:15:12 +0000169 }
robbiewaa01abd2003-03-27 18:39:24 +0000170
Garrett Cooperc548a312011-03-04 02:12:05 -0800171 /*
172 * Wait till all kids have terminated. Stash away their
173 * pid's in an array.
174 */
175 kid_count = 0;
176 errno = 0;
177 while (((ret_val = waitpid(0, &status, WUNTRACED)) != -1) ||
178 (errno == EINTR)) {
179 if (ret_val == -1)
180 continue;
181
182 if (!WIFEXITED(status)) {
183 if (!WIFSTOPPED(status)) {
184 tst_resm(TFAIL, "Child %d is not "
185 "stopped", ret_val);
186 fail = 1;
187 } else {
188 if (WSTOPSIG(status) != SIGSTOP) {
189 tst_resm(TFAIL, "Child %d "
190 "exited with wrong "
191 "status", ret_val);
192 tst_resm(TFAIL, "Expected "
193 "SIGSTOP got %d",
194 WEXITSTATUS(status));
195 fail = 1;
196 }
197 }
198 if (kill(ret_val, SIGCONT) < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800199 tst_resm(TFAIL | TERRNO,
200 "killing child %d failed", ret_val);
Garrett Cooperc548a312011-03-04 02:12:05 -0800201 fail = 1;
202 }
203 }
204 found = 0;
205 for (j = 0; j < kid_count; j++) {
206 if (ret_val == wait_kid_pid[j]) {
207 found = 1;
208 break;
209 }
210 }
211 if (!found)
212 wait_kid_pid[kid_count++] = ret_val;
213 }
214
215 /*
216 * Check that for every entry in the fork_kid_pid array,
217 * there is a matching pid in the wait_kid_pid array. If
218 * not, it's an error.
219 */
220 for (i = 0; i < kid_count; i++) {
221 found = 0;
222 for (j = (MAXKIDS / 2); j < MAXKIDS; j++) {
223 if (fork_kid_pid[j] == wait_kid_pid[i]) {
224 found = 1;
225 break;
226 }
227 }
228 if (!found) {
229 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800230 "for the fork_kid_pid of %d", wait_kid_pid[i]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800231 for (k = 0; k < MAXKIDS; k++)
232 tst_resm(TFAIL, "fork_kid_pid[%d] = "
233 "%d", k, fork_kid_pid[k]);
234 for (k = 0; k < kid_count; k++)
235 tst_resm(TFAIL, "wait_kid_pid[%d] = "
236 "%d", k, wait_kid_pid[k]);
237 fail = 1;
238 }
239 }
240
241 if (kid_count != (MAXKIDS / 2)) {
242 tst_resm(TFAIL, "Wrong number of children waited on "
243 "for pid = 0");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800244 tst_resm(TFAIL, "Expected %d got %d", MAXKIDS, kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800245 fail = 1;
246 }
247
248 /* Make sure can pickup children in a diff. process group */
249
250 kid_count = 0;
251 errno = 0;
252 while (((ret_val = waitpid(-(group1), &status, WUNTRACED)) !=
253 -1) || (errno == EINTR)) {
254 if (ret_val == -1)
255 continue;
256 if (!WIFEXITED(status)) {
257 if (!WIFSTOPPED(status)) {
258 tst_resm(TFAIL, "Child %d is not "
259 "stopped", ret_val);
260 fail = 1;
261 } else {
262 if (WSTOPSIG(status) != SIGSTOP) {
263 tst_resm(TFAIL, "Child %d "
264 "exited with wrong "
265 "status", ret_val);
266 tst_resm(TFAIL, "Expected "
267 "SIGSTOP got %d",
268 WEXITSTATUS(status));
269 fail = 1;
270 }
271 }
272 if (kill(ret_val, SIGCONT) < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800273 tst_resm(TFAIL | TERRNO,
274 "Killing child %d failed", ret_val);
Garrett Cooperc548a312011-03-04 02:12:05 -0800275 fail = 1;
276 }
277 }
278 found = 0;
279 for (j = 0; j < kid_count; j++) {
280 if (ret_val == wait_kid_pid[j]) {
281 found = 1;
282 break;
283 }
284 }
285 if (!found)
286 wait_kid_pid[kid_count++] = ret_val;
287 }
288
289 /*
290 * Check that for every entry in the fork_kid_pid array,
291 * there is a matching pid in the wait_kid_pid array. If
292 * not, it's an error.
293 */
294 for (i = 0; i < kid_count; i++) {
295 found = 0;
296 for (j = 0; j < (MAXKIDS / 2); j++) {
297 if (fork_kid_pid[j] == wait_kid_pid[i]) {
298 found = 1;
299 break;
300 }
301 }
302 if (!found) {
303 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800304 "for the fork_kid_pid of %d", fork_kid_pid[j]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800305 for (k = 0; k < MAXKIDS; k++)
306 tst_resm(TFAIL, "fork_kid_pid[%d] = "
307 "%d", k, fork_kid_pid[k]);
308 for (k = 0; k < kid_count; k++)
309 tst_resm(TFAIL, "wait_kid_pid[%d] = "
310 "%d", k, wait_kid_pid[k]);
311 fail = 1;
312 }
313 }
314 if (kid_count != (MAXKIDS / 2)) {
315 tst_resm(TFAIL, "Wrong number of children waited on "
316 "for pid = 0");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800317 tst_resm(TFAIL, "Expected %d got %d", MAXKIDS, kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800318 fail = 1;
319 }
320
321 /*
322 * Check that waitpid(WUNTRACED) returns -1 when no stopped
323 * children
324 */
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800325 ret_val = waitpid(-1, &status, WUNTRACED);
326 if (ret_val != -1) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800327 tst_resm(TFAIL, "Waitpid returned wrong value.");
328 tst_resm(TFAIL, "Expected -1 got %d", ret_val);
329 fail = 1;
330 }
331
332 if (errno != ECHILD) {
333 tst_resm(TFAIL, "Expected ECHILD from waitpid(WUNTRACED)");
334 fail = 1;
335 }
336
337 if (fail)
338 tst_resm(TFAIL, "Test FAILED");
339 else
340 tst_resm(TPASS, "Test PASSED");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800341
Garrett Cooperc548a312011-03-04 02:12:05 -0800342 tst_exit();
plars865695b2001-08-27 22:15:12 +0000343}
344
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800345static void setup_sigint(void)
robbiewd34d5812005-07-11 22:28:09 +0000346{
Garrett Cooperc548a312011-03-04 02:12:05 -0800347 if (signal(SIGINT, inthandlr) == SIG_ERR)
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800348 tst_brkm(TFAIL | TERRNO, NULL, "signal SIGINT failed");
robbiewd34d5812005-07-11 22:28:09 +0000349}
350
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800351static void setup(void)
plars865695b2001-08-27 22:15:12 +0000352{
plars865695b2001-08-27 22:15:12 +0000353 TEST_PAUSE;
354}
355
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800356static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000357{
Garrett Cooperc548a312011-03-04 02:12:05 -0800358}
plars865695b2001-08-27 22:15:12 +0000359
Mike Frysingerc57fba52014-04-09 18:56:30 -0400360static void inthandlr(void)
plars865695b2001-08-27 22:15:12 +0000361{
362 intintr++;
363}
364
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800365static void wait_for_parent(void)
plars865695b2001-08-27 22:15:12 +0000366{
367 int testvar;
368
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800369 while (!intintr)
plars865695b2001-08-27 22:15:12 +0000370 testvar = 0;
plars865695b2001-08-27 22:15:12 +0000371}
372
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800373static void do_exit(void)
plars865695b2001-08-27 22:15:12 +0000374{
375 wait_for_parent();
376 kill(getpid(), SIGSTOP);
377 exit(3);
378}
robbiewd34d5812005-07-11 22:28:09 +0000379
380#ifdef UCLINUX
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800381static void do_exit_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000382{
383 setup_sigint();
384 do_exit();
385}
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800386#endif