blob: 15d5faeab7c77fbb037f85ac69061a738d154a5f [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 * waitpid07.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 = WNOHANG
29 *
30 * USAGE: <for command-line>
31 * waitpid07 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
32 * where, -c n : Run n copies concurrently.
33 * -e : Turn on errno logging.
34 * -i n : Execute test n times.
35 * -I x : Execute test for x seconds.
36 * -P x : Pause for x seconds between iterations.
37 * -t : Turn on syscall timing.
38 *
39 * History
40 * 07/2001 John George
41 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000042 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000043 *
44 * Restrictions
45 * None
46 */
47
48#include <sys/types.h>
49#include <signal.h>
50#include <errno.h>
51#include <sys/wait.h>
Garrett Coopere8530df2010-12-21 11:37:57 -080052#include "test.h"
plars865695b2001-08-27 22:15:12 +000053
Wanlong Gao5086d422012-11-20 10:32:33 +080054static void setup_sigint(void);
55static void do_child_1(void);
56static void setup(void);
57static void cleanup(void);
plars865695b2001-08-27 22:15:12 +000058
59char *TCID = "waitpid07";
60int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000061
robbiew3d5c7352003-01-13 17:49:51 +000062volatile int intintr;
Wanlong Gao5086d422012-11-20 10:32:33 +080063static int flag;
64static void inthandlr();
65static void do_exit(void);
plars865695b2001-08-27 22:15:12 +000066
67#define FAILED 1
68#define MAXKIDS 8
69
robbiewd34d5812005-07-11 22:28:09 +000070#ifdef UCLINUX
71static char *argv0;
Wanlong Gao5086d422012-11-20 10:32:33 +080072static void do_child_2_uclinux(void);
robbiewd34d5812005-07-11 22:28:09 +000073#endif
74
plars74948ad2002-11-14 16:16:14 +000075int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000076{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020077 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020078 const char *msg;
plars865695b2001-08-27 22:15:12 +000079
robbiewd34d5812005-07-11 22:28:09 +000080 int status;
plars865695b2001-08-27 22:15:12 +000081 int fail = 0;
plars865695b2001-08-27 22:15:12 +000082 int pid;
83
Wanlong Gao5086d422012-11-20 10:32:33 +080084 msg = parse_opts(argc, argv, NULL, NULL);
85 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000086 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080087
robbiewd34d5812005-07-11 22:28:09 +000088#ifdef UCLINUX
89 argv0 = argv[0];
90
91 maybe_run_child(&do_child_1, "n", 1);
92 maybe_run_child(&do_child_2_uclinux, "n", 2);
93#endif
94
plars865695b2001-08-27 22:15:12 +000095 setup();
96
97 /* check for looping state if -i option is given */
98 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +080099 /* reset tst_count in case we are looping */
100 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000101
Wanlong Gao5086d422012-11-20 10:32:33 +0800102 pid = FORK_OR_VFORK();
103 if (pid < 0) {
plars865695b2001-08-27 22:15:12 +0000104 tst_resm(TFAIL, "Fork Failed, may be OK under stress");
plars865695b2001-08-27 22:15:12 +0000105 } else if (pid == 0) {
106
107 /*
108 * Child:
109 * Set up to catch SIGINT. The kids will wait till a
110 * SIGINT has been received before they proceed.
111 */
robbiewd34d5812005-07-11 22:28:09 +0000112#ifdef UCLINUX
113 if (self_exec(argv[0], "n", 1) < 0) {
114 tst_resm(TINFO, "self_exec failed");
115 exit(pid);
plars865695b2001-08-27 22:15:12 +0000116 }
robbiewd34d5812005-07-11 22:28:09 +0000117#else
118 do_child_1();
119#endif
Wanlong Gao5086d422012-11-20 10:32:33 +0800120 } else {
plars865695b2001-08-27 22:15:12 +0000121 fail = 0;
122 waitpid(pid, &status, 0);
123 if (WEXITSTATUS(status) != 0) {
124 tst_resm(TFAIL, "child returned bad status");
125 fail = 1;
126 }
Wanlong Gao5086d422012-11-20 10:32:33 +0800127 if (fail)
plars865695b2001-08-27 22:15:12 +0000128 tst_resm(TFAIL, "%s FAILED", TCID);
Wanlong Gao5086d422012-11-20 10:32:33 +0800129 else
plars865695b2001-08-27 22:15:12 +0000130 tst_resm(TPASS, "%s PASSED", TCID);
plars865695b2001-08-27 22:15:12 +0000131 }
132 }
Wanlong Gao5086d422012-11-20 10:32:33 +0800133
plars865695b2001-08-27 22:15:12 +0000134 cleanup();
Garrett Cooper7d0a4a52010-12-16 10:05:08 -0800135 tst_exit();
plars865695b2001-08-27 22:15:12 +0000136}
137
138/*
robbiewd34d5812005-07-11 22:28:09 +0000139 * setup_sigint()
140 * Sets up a SIGINT handler
141 */
Wanlong Gao5086d422012-11-20 10:32:33 +0800142static void setup_sigint(void)
robbiewd34d5812005-07-11 22:28:09 +0000143{
subrata_modak56207ce2009-03-23 13:35:39 +0000144 if ((sig_t) signal(SIGINT, inthandlr) == SIG_ERR) {
145 tst_resm(TFAIL, "signal SIGINT failed. " "errno = %d", errno);
robbiewd34d5812005-07-11 22:28:09 +0000146 exit(-1);
147 }
148}
149
Wanlong Gao5086d422012-11-20 10:32:33 +0800150static void do_child_1(void)
robbiewd34d5812005-07-11 22:28:09 +0000151{
152 int kid_count, fork_kid_pid[MAXKIDS];
153 int ret_val;
154 int i, j, k, found;
155 int group1, group2;
156 int wait_kid_pid[MAXKIDS], status;
157
158 setup_sigint();
subrata_modakbdbaec52009-02-26 12:14:51 +0000159
robbiewd34d5812005-07-11 22:28:09 +0000160 group1 = getpgrp();
161
162 for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
Wanlong Gao5086d422012-11-20 10:32:33 +0800163 if (kid_count == (MAXKIDS / 2))
robbiewd34d5812005-07-11 22:28:09 +0000164 group2 = setpgrp();
robbiewd34d5812005-07-11 22:28:09 +0000165
166 intintr = 0;
167 ret_val = FORK_OR_VFORK();
168 if (ret_val == 0) {
169#ifdef UCLINUX
170 if (self_exec(argv0, "n", 2) < 0) {
171 tst_resm(TFAIL, "Fork kid %d failed. "
subrata_modak56207ce2009-03-23 13:35:39 +0000172 "errno = %d", kid_count, errno);
robbiewd34d5812005-07-11 22:28:09 +0000173 exit(ret_val);
174 }
175#else
176 do_exit();
177#endif
Wanlong Gao5086d422012-11-20 10:32:33 +0800178 }
robbiewd34d5812005-07-11 22:28:09 +0000179
180 if (ret_val < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100181 tst_brkm(TFAIL, NULL, "Fork kid %d failed. "
robbiewd34d5812005-07-11 22:28:09 +0000182 "errno = %d", kid_count, errno);
robbiewd34d5812005-07-11 22:28:09 +0000183 }
184
185 /* parent */
186 fork_kid_pid[kid_count] = ret_val;
187 }
188
189 /* Check that waitpid with WNOHANG returns zero */
Wanlong Gao5086d422012-11-20 10:32:33 +0800190 ret_val = waitpid(-1, &status, WNOHANG);
191 if (ret_val != 0) {
robbiewd34d5812005-07-11 22:28:09 +0000192 tst_resm(TFAIL, "Waitpid returned wrong value");
subrata_modak56207ce2009-03-23 13:35:39 +0000193 tst_resm(TFAIL, "Expected 0 got %d", ret_val);
robbiewd34d5812005-07-11 22:28:09 +0000194 flag = FAILED;
195 }
robbiewd34d5812005-07-11 22:28:09 +0000196#ifdef UCLINUX
197 /* Give the kids a chance to setup SIGINT again, since this is
198 * cleared by exec().
199 */
200 sleep(3);
201#endif
202
203 /* Now send all the kids a SIGINT to tell them to
204 * proceed
205 */
206 for (i = 0; i < MAXKIDS; i++) {
207 if (kill(fork_kid_pid[i], SIGINT) < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100208 tst_brkm(TFAIL, NULL, "Kill of child %d "
robbiewd34d5812005-07-11 22:28:09 +0000209 "failed, errno = %d", i, errno);
robbiewd34d5812005-07-11 22:28:09 +0000210 }
211 }
212
213 /*
214 * Wait till all kids have terminated. Stash away their
215 * pid's in an array.
216 */
217 kid_count = 0;
218 errno = 0;
219 while (((ret_val = waitpid(-1, &status, WNOHANG)) != -1)
220 || (errno == EINTR)) {
Wanlong Gao5086d422012-11-20 10:32:33 +0800221 if ((ret_val == -1) || (ret_val == 0))
robbiewd34d5812005-07-11 22:28:09 +0000222 continue;
robbiewd34d5812005-07-11 22:28:09 +0000223
224 if (!WIFEXITED(status)) {
225 tst_resm(TFAIL, "Child %d did not exit "
226 "normally", ret_val);
227 flag = FAILED;
228 } else {
229 if (WEXITSTATUS(status) != 3) {
230 tst_resm(TFAIL, "Child %d "
231 "exited with wrong "
232 "status", ret_val);
233 tst_resm(TFAIL, "Expected 3 "
subrata_modak56207ce2009-03-23 13:35:39 +0000234 "got %d ", WEXITSTATUS(status));
robbiewd34d5812005-07-11 22:28:09 +0000235 flag = FAILED;
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; j++) {
subrata_modak56207ce2009-03-23 13:35:39 +0000249 if (fork_kid_pid[j] == wait_kid_pid[i]) {
robbiewd34d5812005-07-11 22:28:09 +0000250 found = 1;
251 break;
252 }
253 }
254
255 if (!found) {
256 tst_resm(TFAIL, "Did not find a "
257 "wait_kid_pid for the "
subrata_modak56207ce2009-03-23 13:35:39 +0000258 "fork_kid_pid of %d", wait_kid_pid[i]);
robbiewd34d5812005-07-11 22:28:09 +0000259 for (k = 0; k < MAXKIDS; k++) {
260 tst_resm(TFAIL,
261 "fork_kid_pid[%d] = "
subrata_modak56207ce2009-03-23 13:35:39 +0000262 "%d", k, fork_kid_pid[k]);
robbiewd34d5812005-07-11 22:28:09 +0000263 }
264 for (k = 0; k < kid_count; k++) {
265 tst_resm(TFAIL,
266 "wait_kid_pid[%d] = "
subrata_modak56207ce2009-03-23 13:35:39 +0000267 "%d", k, wait_kid_pid[k]);
robbiewd34d5812005-07-11 22:28:09 +0000268 }
269 flag = FAILED;
270 }
271 }
272
Wanlong Gao5086d422012-11-20 10:32:33 +0800273 if (flag)
robbiewd34d5812005-07-11 22:28:09 +0000274 exit(1);
Wanlong Gao5086d422012-11-20 10:32:33 +0800275 else
robbiewd34d5812005-07-11 22:28:09 +0000276 exit(0);
robbiewd34d5812005-07-11 22:28:09 +0000277}
278
279#ifdef UCLINUX
280/*
281 * do_child_2_uclinux()
282 * sets up sigint handler again, then calls the normal child 2 function
283 */
Wanlong Gao5086d422012-11-20 10:32:33 +0800284static void do_child_2_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000285{
286 setup_sigint();
287 do_exit();
288}
289#endif
290
Wanlong Gao5086d422012-11-20 10:32:33 +0800291static void setup(void)
plars865695b2001-08-27 22:15:12 +0000292{
plars865695b2001-08-27 22:15:12 +0000293 TEST_PAUSE;
294}
295
Wanlong Gao5086d422012-11-20 10:32:33 +0800296static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000297{
Wanlong Gao5086d422012-11-20 10:32:33 +0800298}
plars865695b2001-08-27 22:15:12 +0000299
Mike Frysingerc57fba52014-04-09 18:56:30 -0400300static void inthandlr(void)
plars865695b2001-08-27 22:15:12 +0000301{
302 intintr++;
303}
304
Wanlong Gao5086d422012-11-20 10:32:33 +0800305static void wait_for_parent(void)
plars865695b2001-08-27 22:15:12 +0000306{
307 int testvar;
308
Wanlong Gao5086d422012-11-20 10:32:33 +0800309 while (!intintr)
plars865695b2001-08-27 22:15:12 +0000310 testvar = 0;
plars865695b2001-08-27 22:15:12 +0000311}
312
Wanlong Gao5086d422012-11-20 10:32:33 +0800313static void do_exit(void)
plars865695b2001-08-27 22:15:12 +0000314{
315 wait_for_parent();
316 exit(3);
Chris Dearmanec6edca2012-10-17 19:54:01 -0700317}