blob: ae1acc4fca6b8917f7706d61a7ee84769e7218be [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 * waitpid11.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
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
Wanlong Gaof1fd88c2012-11-20 10:32:33 +080041 * None
plars865695b2001-08-27 22:15:12 +000042 */
43
44#include <sys/types.h>
45#include <signal.h>
46#include <errno.h>
47#include <sys/wait.h>
Garrett Coopere8530df2010-12-21 11:37:57 -080048#include "test.h"
plars865695b2001-08-27 22:15:12 +000049
50#define MAXKIDS 8
51
52char *TCID = "waitpid11";
53int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000054
robbiew3d5c7352003-01-13 17:49:51 +000055volatile int intintr;
Wanlong Gaof1fd88c2012-11-20 10:32:33 +080056static void setup(void);
57static void cleanup(void);
58static void inthandlr();
59static void wait_for_parent(void);
60static void do_exit(void);
61static void setup_sigint(void);
robbiewd34d5812005-07-11 22:28:09 +000062#ifdef UCLINUX
Wanlong Gaof1fd88c2012-11-20 10:32:33 +080063static void do_exit_uclinux(void);
robbiewd34d5812005-07-11 22:28:09 +000064#endif
plars865695b2001-08-27 22:15:12 +000065
Wanlong Gaof1fd88c2012-11-20 10:32:33 +080066static int fail;
plars865695b2001-08-27 22:15:12 +000067
plarsac85d1c2002-06-10 14:52:37 +000068int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000069{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020070 const char *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +000071
plars865695b2001-08-27 22:15:12 +000072 int kid_count, ret_val, status;
plars74948ad2002-11-14 16:16:14 +000073 int i, j, k, found;
plars865695b2001-08-27 22:15:12 +000074 int group1, group2;
75 int fork_kid_pid[MAXKIDS], wait_kid_pid[MAXKIDS];
76 int pid;
77
Wanlong Gaof1fd88c2012-11-20 10:32:33 +080078 msg = parse_opts(ac, av, NULL, NULL);
79 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000080 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080081
robbiewd34d5812005-07-11 22:28:09 +000082#ifdef UCLINUX
83 maybe_run_child(&do_exit_uclinux, "");
84#endif
85
plars865695b2001-08-27 22:15:12 +000086 setup();
87
Caspar Zhangd59a6592013-03-07 14:59:12 +080088 tst_count = 0;
Garrett Cooperc548a312011-03-04 02:12:05 -080089 fail = 0;
plars865695b2001-08-27 22:15:12 +000090
Garrett Cooperc548a312011-03-04 02:12:05 -080091 /*
92 * Need to have test run from child as test driver causes
93 * test to be a session leader and setpgrp fails.
94 */
plars865695b2001-08-27 22:15:12 +000095
Wanlong Gaof1fd88c2012-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);
107 cleanup();
108 tst_exit();
109 } else if (pid < 0)
110 tst_brkm(TBROK, cleanup, "fork failed");
plars865695b2001-08-27 22:15:12 +0000111
Garrett Cooperc548a312011-03-04 02:12:05 -0800112 /*
113 * Set up to catch SIGINT. The kids will wait till a SIGINT
114 * has been received before they proceed.
115 */
116 setup_sigint();
117
118 group1 = getpgrp();
119
120 for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
121 if (kid_count == (MAXKIDS / 2))
122 group2 = setpgrp();
123
124 intintr = 0;
125 ret_val = FORK_OR_VFORK();
126 if (ret_val == 0) {
127#ifdef UCLINUX
128 if (self_exec(av[0], "") < 0)
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800129 tst_resm(TFAIL | TERRNO, "self_exec kid %d "
Garrett Cooperc548a312011-03-04 02:12:05 -0800130 "failed", kid_count);
131#else
132 do_exit();
133#endif
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800134 }
plars865695b2001-08-27 22:15:12 +0000135
Garrett Cooperc548a312011-03-04 02:12:05 -0800136 if (ret_val < 0)
137 tst_resm(TFAIL, "Fork kid %d failed. errno = "
138 "%d", kid_count, errno);
plars865695b2001-08-27 22:15:12 +0000139
Garrett Cooperc548a312011-03-04 02:12:05 -0800140 /* parent */
141 fork_kid_pid[kid_count] = ret_val;
142 }
robbiewd34d5812005-07-11 22:28:09 +0000143
144#ifdef UCLINUX
Garrett Cooperc548a312011-03-04 02:12:05 -0800145 /* Give the kids a chance to setup SIGINT again, since this is
146 * cleared by exec().
147 */
148 sleep(3);
robbiewd34d5812005-07-11 22:28:09 +0000149#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000150
Garrett Cooperc548a312011-03-04 02:12:05 -0800151 /* Now send all the kids a SIGINT to tell them to proceed */
152 for (i = 0; i < MAXKIDS; i++)
153 if (kill(fork_kid_pid[i], SIGINT) < 0)
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800154 tst_resm(TFAIL | TERRNO, "Kill of child %d failed", i);
Garrett Cooper2c282152010-12-16 00:55:50 -0800155
Garrett Cooperc548a312011-03-04 02:12:05 -0800156 /*
157 * Wait till all kids have terminated. Stash away their
158 * pid's in an array.
159 */
160 kid_count = 0;
161 errno = 0;
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800162 while (((ret_val = waitpid(0, &status, 0)) != -1) || (errno == EINTR)) {
Garrett Cooperc548a312011-03-04 02:12:05 -0800163 if (ret_val == -1)
164 continue;
plars865695b2001-08-27 22:15:12 +0000165
Garrett Cooperc548a312011-03-04 02:12:05 -0800166 if (!WIFEXITED(status)) {
167 tst_resm(TFAIL, "Child %d did not exit "
168 "normally", ret_val);
plars865695b2001-08-27 22:15:12 +0000169 fail = 1;
plars865695b2001-08-27 22:15:12 +0000170 } else {
Garrett Cooperc548a312011-03-04 02:12:05 -0800171 if (WEXITSTATUS(status) != 3) {
172 tst_resm(TFAIL, "Child %d exited with "
173 "wrong status", ret_val);
174 tst_resm(TFAIL, "Expected 3 got %d",
175 WEXITSTATUS(status));
176 fail = 1;
177 }
178 }
179 wait_kid_pid[kid_count++] = ret_val;
180 }
181
182 /*
183 * Check that for every entry in the fork_kid_pid array,
184 * there is a matching pid in the wait_kid_pid array. If
185 * not, it's an error.
186 */
187 for (i = 0; i < kid_count; i++) {
188 found = 0;
189 for (j = (MAXKIDS / 2); j < MAXKIDS; j++) {
190 if (fork_kid_pid[j] == wait_kid_pid[i]) {
191 found = 1;
192 break;
193 }
194 }
195 if (!found) {
196 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800197 "for the fork_kid_pid of %d", wait_kid_pid[i]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800198 for (k = 0; k < MAXKIDS; k++) {
199 tst_resm(TFAIL, "fork_kid_pid[%d] = "
200 "%d", k, fork_kid_pid[k]);
201 }
202 for (k = 0; k < kid_count; k++) {
203 tst_resm(TFAIL, "wait_kid_pid[%d] = "
204 "%d", k, wait_kid_pid[k]);
205 }
206 fail = 1;
plars865695b2001-08-27 22:15:12 +0000207 }
208 }
robbiewaa01abd2003-03-27 18:39:24 +0000209
Garrett Cooperc548a312011-03-04 02:12:05 -0800210 if (kid_count != (MAXKIDS / 2)) {
211 tst_resm(TFAIL, "Wrong number of children waited on "
212 "for pid = 0");
213 tst_resm(TFAIL, "Expected 4 got %d", kid_count);
214 fail = 1;
215 }
216
217 /* Make sure can pickup children in a diff. process group */
218
219 kid_count = 0;
220 errno = 0;
221 while (((ret_val = waitpid(-(group1), &status, 0)) != -1) ||
222 (errno == EINTR)) {
223 if (ret_val == -1)
224 continue;
225 if (!WIFEXITED(status)) {
226 tst_resm(TFAIL, "Child %d did not exit "
227 "normally", ret_val);
228 fail = 1;
229 } else {
230 if (WEXITSTATUS(status) != 3) {
231 tst_resm(TFAIL, "Child %d exited with "
232 "wrong status", ret_val);
233 tst_resm(TFAIL, "Expected 3 got %d",
234 WEXITSTATUS(status));
235 fail = 1;
236 }
237 }
238 wait_kid_pid[kid_count++] = ret_val;
239 }
240
241 /*
242 * Check that for every entry in the fork_kid_pid array,
243 * there is a matching pid in the wait_kid_pid array. If
244 * not, it's an error.
245 */
246 for (i = 0; i < kid_count; i++) {
247 found = 0;
248 for (j = 0; j < (MAXKIDS / 2); j++) {
249 if (fork_kid_pid[j] == wait_kid_pid[i]) {
250 found = 1;
251 break;
252 }
253 }
254 if (!found) {
255 tst_resm(TFAIL, "Did not find a wait_kid_pid "
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800256 "for the fork_kid_pid of %d", fork_kid_pid[j]);
Garrett Cooperc548a312011-03-04 02:12:05 -0800257 for (k = 0; k < MAXKIDS; k++)
258 tst_resm(TFAIL, "fork_kid_pid[%d] = "
259 "%d", k, fork_kid_pid[k]);
260 for (k = 0; k < kid_count; k++)
261 tst_resm(TFAIL, "wait_kid_pid[%d] = "
262 "%d", k, wait_kid_pid[k]);
263 fail = 1;
264 }
265 }
266 if (kid_count != (MAXKIDS / 2)) {
267 tst_resm(TFAIL, "Wrong number of children waited on "
268 "for pid = 0");
269 tst_resm(TFAIL, "Expected 4 got %d", kid_count);
270 fail = 1;
271 }
272
273 if (fail)
274 tst_resm(TFAIL, "Test FAILED");
275 else
276 tst_resm(TPASS, "Test PASSED");
277
278 tst_exit();
plars865695b2001-08-27 22:15:12 +0000279}
280
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800281static void setup_sigint(void)
robbiewd34d5812005-07-11 22:28:09 +0000282{
Garrett Cooperc548a312011-03-04 02:12:05 -0800283 if (signal(SIGINT, inthandlr) == SIG_ERR)
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800284 tst_brkm(TFAIL | TERRNO, NULL, "signal SIGINT failed");
robbiewd34d5812005-07-11 22:28:09 +0000285}
286
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800287static void setup(void)
plars865695b2001-08-27 22:15:12 +0000288{
plars865695b2001-08-27 22:15:12 +0000289 TEST_PAUSE;
290}
291
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800292static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000293{
Garrett Cooperc548a312011-03-04 02:12:05 -0800294}
subrata_modak56207ce2009-03-23 13:35:39 +0000295
Mike Frysingerc57fba52014-04-09 18:56:30 -0400296static void inthandlr(void)
plars865695b2001-08-27 22:15:12 +0000297{
298 intintr++;
299}
300
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800301static void wait_for_parent(void)
plars865695b2001-08-27 22:15:12 +0000302{
303 int testvar;
304
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800305 while (!intintr)
plars865695b2001-08-27 22:15:12 +0000306 testvar = 0;
plars865695b2001-08-27 22:15:12 +0000307}
308
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800309static void do_exit(void)
plars865695b2001-08-27 22:15:12 +0000310{
311 wait_for_parent();
312 exit(3);
313}
robbiewd34d5812005-07-11 22:28:09 +0000314
315#ifdef UCLINUX
Wanlong Gaof1fd88c2012-11-20 10:32:33 +0800316static void do_exit_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000317{
318 setup_sigint();
319 do_exit();
320}
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800321#endif