blob: c95b44aa2ed18662bed869728811fc3aa200a325 [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"
50#include "usctest.h"
plars865695b2001-08-27 22:15:12 +000051
52#define MAXKIDS 8
53
54char *TCID = "waitpid13";
55int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000056
robbiew3d5c7352003-01-13 17:49:51 +000057volatile int intintr;
Wanlong Gao04cfe1b2012-11-20 10:32:33 +080058static void setup(void);
59static void cleanup(void);
60static void inthandlr();
61static void wait_for_parent(void);
62static void do_exit(void);
63static void setup_sigint(void);
robbiewd34d5812005-07-11 22:28:09 +000064#ifdef UCLINUX
Wanlong Gao04cfe1b2012-11-20 10:32:33 +080065static void do_exit_uclinux(void);
robbiewd34d5812005-07-11 22:28:09 +000066#endif
plars865695b2001-08-27 22:15:12 +000067
Wanlong Gao04cfe1b2012-11-20 10:32:33 +080068static int fail;
plars865695b2001-08-27 22:15:12 +000069
plarsac85d1c2002-06-10 14:52:37 +000070int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000071{
Garrett Cooperc548a312011-03-04 02:12:05 -080072 char *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +000073
plars74948ad2002-11-14 16:16:14 +000074 int kid_count, ret_val, status;
75 int i, j, k, found;
plars865695b2001-08-27 22:15:12 +000076 int group1, group2;
77 int fork_kid_pid[MAXKIDS], wait_kid_pid[MAXKIDS];
78 int pid;
79
Wanlong Gao04cfe1b2012-11-20 10:32:33 +080080 msg = parse_opts(ac, av, NULL, NULL);
81 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000082 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Wanlong Gao04cfe1b2012-11-20 10:32:33 +080083
robbiewd34d5812005-07-11 22:28:09 +000084#ifdef UCLINUX
85 maybe_run_child(&do_exit_uclinux, "");
86#endif
87
plars865695b2001-08-27 22:15:12 +000088 setup();
89
Caspar Zhangd59a6592013-03-07 14:59:12 +080090 tst_count = 0;
Garrett Cooperc548a312011-03-04 02:12:05 -080091 fail = 0;
plars865695b2001-08-27 22:15:12 +000092
Garrett Cooperc548a312011-03-04 02:12:05 -080093 /*
94 * Need to have test run from child as test driver causes
95 * test to be a session leader and setpgrp fails.
96 */
Wanlong Gao04cfe1b2012-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);
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800108
Garrett Cooperc548a312011-03-04 02:12:05 -0800109 cleanup();
110 tst_exit();
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800111 } else if (pid < 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800112 tst_brkm(TBROK, cleanup, "fork failed");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800113 }
plars865695b2001-08-27 22:15:12 +0000114
Garrett Cooperc548a312011-03-04 02:12:05 -0800115 /*
116 * Set up to catch SIGINT. The kids will wait till a SIGINT
117 * has been received before they proceed.
118 */
119 setup_sigint();
plars865695b2001-08-27 22:15:12 +0000120
Garrett Cooperc548a312011-03-04 02:12:05 -0800121 group1 = getpgrp();
plars865695b2001-08-27 22:15:12 +0000122
Garrett Cooperc548a312011-03-04 02:12:05 -0800123 for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
124 if (kid_count == (MAXKIDS / 2))
125 group2 = setpgrp();
plars865695b2001-08-27 22:15:12 +0000126
Garrett Cooperc548a312011-03-04 02:12:05 -0800127 intintr = 0;
128 ret_val = FORK_OR_VFORK();
129 if (ret_val == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000130#ifdef UCLINUX
Garrett Cooperc548a312011-03-04 02:12:05 -0800131 if (self_exec(av[0], "") < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800132 tst_resm(TFAIL | TERRNO, "self_exec kid %d "
Garrett Cooperc548a312011-03-04 02:12:05 -0800133 "failed", kid_count);
Garrett Cooper2c282152010-12-16 00:55:50 -0800134
Garrett Cooperc548a312011-03-04 02:12:05 -0800135 }
robbiewd34d5812005-07-11 22:28:09 +0000136#else
Garrett Cooperc548a312011-03-04 02:12:05 -0800137 do_exit();
robbiewd34d5812005-07-11 22:28:09 +0000138#endif
plars865695b2001-08-27 22:15:12 +0000139 }
140
Garrett Cooperc548a312011-03-04 02:12:05 -0800141 if (ret_val < 0)
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800142 tst_resm(TFAIL | TERRNO, "forking kid %d failed",
143 kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800144
145 /* parent */
146 fork_kid_pid[kid_count] = ret_val;
147 }
148
149 /* Check that waitpid with WNOHANG|WUNTRACED returns zero */
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800150 ret_val = waitpid(0, &status, WNOHANG | WUNTRACED);
151 if (ret_val != 0) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800152 tst_resm(TFAIL, "Waitpid returned wrong value"
153 "from waitpid(WNOHANG|WUNTRACED)");
154 tst_resm(TFAIL, "Expected 0 got %d", ret_val);
155 fail = 1;
156 }
robbiewd34d5812005-07-11 22:28:09 +0000157#ifdef UCLINUX
Garrett Cooperc548a312011-03-04 02:12:05 -0800158 /* Give the kids a chance to setup SIGINT again, since this is
159 * cleared by exec().
160 */
161 sleep(3);
robbiewd34d5812005-07-11 22:28:09 +0000162#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000163
Garrett Cooperc548a312011-03-04 02:12:05 -0800164 /* Now send all the kids a SIGINT to tell them to proceed */
165 for (i = 0; i < MAXKIDS; i++) {
166 if (kill(fork_kid_pid[i], SIGINT) < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800167 tst_resm(TFAIL | TERRNO, "killing child %d failed", i);
plars865695b2001-08-27 22:15:12 +0000168 fail = 1;
169 }
plars865695b2001-08-27 22:15:12 +0000170 }
robbiewaa01abd2003-03-27 18:39:24 +0000171
Garrett Cooperc548a312011-03-04 02:12:05 -0800172 /*
173 * Wait till all kids have terminated. Stash away their
174 * pid's in an array.
175 */
176 kid_count = 0;
177 errno = 0;
178 while (((ret_val = waitpid(0, &status, WUNTRACED)) != -1) ||
179 (errno == EINTR)) {
180 if (ret_val == -1)
181 continue;
182
183 if (!WIFEXITED(status)) {
184 if (!WIFSTOPPED(status)) {
185 tst_resm(TFAIL, "Child %d is not "
186 "stopped", ret_val);
187 fail = 1;
188 } else {
189 if (WSTOPSIG(status) != SIGSTOP) {
190 tst_resm(TFAIL, "Child %d "
191 "exited with wrong "
192 "status", ret_val);
193 tst_resm(TFAIL, "Expected "
194 "SIGSTOP got %d",
195 WEXITSTATUS(status));
196 fail = 1;
197 }
198 }
199 if (kill(ret_val, SIGCONT) < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800200 tst_resm(TFAIL | TERRNO,
201 "killing child %d failed", ret_val);
Garrett Cooperc548a312011-03-04 02:12:05 -0800202 fail = 1;
203 }
204 }
205 found = 0;
206 for (j = 0; j < kid_count; j++) {
207 if (ret_val == wait_kid_pid[j]) {
208 found = 1;
209 break;
210 }
211 }
212 if (!found)
213 wait_kid_pid[kid_count++] = ret_val;
214 }
215
216 /*
217 * Check that for every entry in the fork_kid_pid array,
218 * there is a matching pid in the wait_kid_pid array. If
219 * not, it's an error.
220 */
221 for (i = 0; i < kid_count; i++) {
222 found = 0;
223 for (j = (MAXKIDS / 2); j < MAXKIDS; j++) {
224 if (fork_kid_pid[j] == wait_kid_pid[i]) {
225 found = 1;
226 break;
227 }
228 }
229 if (!found) {
230 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800231 "for the fork_kid_pid of %d", wait_kid_pid[i]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800232 for (k = 0; k < MAXKIDS; k++)
233 tst_resm(TFAIL, "fork_kid_pid[%d] = "
234 "%d", k, fork_kid_pid[k]);
235 for (k = 0; k < kid_count; k++)
236 tst_resm(TFAIL, "wait_kid_pid[%d] = "
237 "%d", k, wait_kid_pid[k]);
238 fail = 1;
239 }
240 }
241
242 if (kid_count != (MAXKIDS / 2)) {
243 tst_resm(TFAIL, "Wrong number of children waited on "
244 "for pid = 0");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800245 tst_resm(TFAIL, "Expected %d got %d", MAXKIDS, kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800246 fail = 1;
247 }
248
249 /* Make sure can pickup children in a diff. process group */
250
251 kid_count = 0;
252 errno = 0;
253 while (((ret_val = waitpid(-(group1), &status, WUNTRACED)) !=
254 -1) || (errno == EINTR)) {
255 if (ret_val == -1)
256 continue;
257 if (!WIFEXITED(status)) {
258 if (!WIFSTOPPED(status)) {
259 tst_resm(TFAIL, "Child %d is not "
260 "stopped", ret_val);
261 fail = 1;
262 } else {
263 if (WSTOPSIG(status) != SIGSTOP) {
264 tst_resm(TFAIL, "Child %d "
265 "exited with wrong "
266 "status", ret_val);
267 tst_resm(TFAIL, "Expected "
268 "SIGSTOP got %d",
269 WEXITSTATUS(status));
270 fail = 1;
271 }
272 }
273 if (kill(ret_val, SIGCONT) < 0) {
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800274 tst_resm(TFAIL | TERRNO,
275 "Killing child %d failed", ret_val);
Garrett Cooperc548a312011-03-04 02:12:05 -0800276 fail = 1;
277 }
278 }
279 found = 0;
280 for (j = 0; j < kid_count; j++) {
281 if (ret_val == wait_kid_pid[j]) {
282 found = 1;
283 break;
284 }
285 }
286 if (!found)
287 wait_kid_pid[kid_count++] = ret_val;
288 }
289
290 /*
291 * Check that for every entry in the fork_kid_pid array,
292 * there is a matching pid in the wait_kid_pid array. If
293 * not, it's an error.
294 */
295 for (i = 0; i < kid_count; i++) {
296 found = 0;
297 for (j = 0; j < (MAXKIDS / 2); j++) {
298 if (fork_kid_pid[j] == wait_kid_pid[i]) {
299 found = 1;
300 break;
301 }
302 }
303 if (!found) {
304 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800305 "for the fork_kid_pid of %d", fork_kid_pid[j]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800306 for (k = 0; k < MAXKIDS; k++)
307 tst_resm(TFAIL, "fork_kid_pid[%d] = "
308 "%d", k, fork_kid_pid[k]);
309 for (k = 0; k < kid_count; k++)
310 tst_resm(TFAIL, "wait_kid_pid[%d] = "
311 "%d", k, wait_kid_pid[k]);
312 fail = 1;
313 }
314 }
315 if (kid_count != (MAXKIDS / 2)) {
316 tst_resm(TFAIL, "Wrong number of children waited on "
317 "for pid = 0");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800318 tst_resm(TFAIL, "Expected %d got %d", MAXKIDS, kid_count);
Garrett Cooperc548a312011-03-04 02:12:05 -0800319 fail = 1;
320 }
321
322 /*
323 * Check that waitpid(WUNTRACED) returns -1 when no stopped
324 * children
325 */
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800326 ret_val = waitpid(-1, &status, WUNTRACED);
327 if (ret_val != -1) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800328 tst_resm(TFAIL, "Waitpid returned wrong value.");
329 tst_resm(TFAIL, "Expected -1 got %d", ret_val);
330 fail = 1;
331 }
332
333 if (errno != ECHILD) {
334 tst_resm(TFAIL, "Expected ECHILD from waitpid(WUNTRACED)");
335 fail = 1;
336 }
337
338 if (fail)
339 tst_resm(TFAIL, "Test FAILED");
340 else
341 tst_resm(TPASS, "Test PASSED");
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800342
Garrett Cooperc548a312011-03-04 02:12:05 -0800343 tst_exit();
plars865695b2001-08-27 22:15:12 +0000344}
345
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800346static void setup_sigint(void)
robbiewd34d5812005-07-11 22:28:09 +0000347{
Garrett Cooperc548a312011-03-04 02:12:05 -0800348 if (signal(SIGINT, inthandlr) == SIG_ERR)
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800349 tst_brkm(TFAIL | TERRNO, NULL, "signal SIGINT failed");
robbiewd34d5812005-07-11 22:28:09 +0000350}
351
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800352static void setup(void)
plars865695b2001-08-27 22:15:12 +0000353{
plars865695b2001-08-27 22:15:12 +0000354 TEST_PAUSE;
355}
356
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800357static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000358{
plars865695b2001-08-27 22:15:12 +0000359 TEST_CLEANUP;
Garrett Cooperc548a312011-03-04 02:12:05 -0800360}
plars865695b2001-08-27 22:15:12 +0000361
Mike Frysingerc57fba52014-04-09 18:56:30 -0400362static void inthandlr(void)
plars865695b2001-08-27 22:15:12 +0000363{
364 intintr++;
365}
366
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800367static void wait_for_parent(void)
plars865695b2001-08-27 22:15:12 +0000368{
369 int testvar;
370
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800371 while (!intintr)
plars865695b2001-08-27 22:15:12 +0000372 testvar = 0;
plars865695b2001-08-27 22:15:12 +0000373}
374
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800375static void do_exit(void)
plars865695b2001-08-27 22:15:12 +0000376{
377 wait_for_parent();
378 kill(getpid(), SIGSTOP);
379 exit(3);
380}
robbiewd34d5812005-07-11 22:28:09 +0000381
382#ifdef UCLINUX
Wanlong Gao04cfe1b2012-11-20 10:32:33 +0800383static void do_exit_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000384{
385 setup_sigint();
386 do_exit();
387}
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800388#endif