blob: 68db9c725a59f404af34e35355f37851bda7cf01 [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
Wanlong Gao4aeecee2012-11-20 10:32:33 +080022 * waitpid09.c
plars865695b2001-08-27 22:15:12 +000023 *
24 * DESCRIPTION
25 * Check ability of parent to wait until child returns, and that the
26 * child's process id is returned through the waitpid. Check that
27 * waitpid returns immediately if no child is present.
subrata_modakbdbaec52009-02-26 12:14:51 +000028 *
plars865695b2001-08-27 22:15:12 +000029 * ALGORITHM
30 * case 0:
31 * Parent forks a child and waits. Parent should do nothing
32 * further until child returns. The pid of the forked child
33 * should match the returned value from the waitpid.
34 *
35 * case 1:
36 * Parent calls a waitpid with no children waiting. Waitpid
37 * should return a -1 since there are no children to wait for.
Garrett Cooper2c282152010-12-16 00:55:50 -080038 *
plars865695b2001-08-27 22:15:12 +000039 * USAGE: <for command-line>
40 * waitpid09 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
41 * where, -c n : Run n copies concurrently.
42 * -e : Turn on errno logging.
43 * -i n : Execute test n times.
44 * -I x : Execute test for x seconds.
45 * -P x : Pause for x seconds between iterations.
46 * -t : Turn on syscall timing.
Garrett Cooper2c282152010-12-16 00:55:50 -080047 *
plars865695b2001-08-27 22:15:12 +000048 * History
49 * 07/2001 John George
subrata_modak4bb656a2009-02-26 12:02:09 +000050 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000051 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000052 *
53 * Restrictions
54 * None
55 */
56
robbiew5832f9b2002-08-12 14:57:23 +000057#define _GNU_SOURCE 1
plars865695b2001-08-27 22:15:12 +000058#include <sys/types.h>
59#include <signal.h>
60#include <errno.h>
61#include <sys/wait.h>
robbiew5832f9b2002-08-12 14:57:23 +000062#include <stdlib.h>
63
plars865695b2001-08-27 22:15:12 +000064#include "test.h"
plars865695b2001-08-27 22:15:12 +000065
66char *TCID = "waitpid09";
67int TST_TOTAL = 1;
robbiew3d5c7352003-01-13 17:49:51 +000068volatile int intintr;
plars865695b2001-08-27 22:15:12 +000069
Wanlong Gao4aeecee2012-11-20 10:32:33 +080070static void setup(void);
71static void cleanup(void);
72static void inthandlr();
73static void do_exit(void);
74static void setup_sigint(void);
robbiewd34d5812005-07-11 22:28:09 +000075#ifdef UCLINUX
Wanlong Gao4aeecee2012-11-20 10:32:33 +080076static void do_exit_uclinux(void);
robbiewd34d5812005-07-11 22:28:09 +000077#endif
plars865695b2001-08-27 22:15:12 +000078
plarsac85d1c2002-06-10 14:52:37 +000079int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000080{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020081 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020082 const char *msg;
plars865695b2001-08-27 22:15:12 +000083
84 int fail, pid, status, ret;
85
Wanlong Gao4aeecee2012-11-20 10:32:33 +080086 msg = parse_opts(argc, argv, NULL, NULL);
87 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000088 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080089
robbiewd34d5812005-07-11 22:28:09 +000090#ifdef UCLINUX
91 maybe_run_child(&do_exit_uclinux, "");
92#endif
93
plars865695b2001-08-27 22:15:12 +000094 setup();
95
Wanlong Gao4aeecee2012-11-20 10:32:33 +080096 pid = FORK_OR_VFORK();
97 if (pid < 0) {
plars865695b2001-08-27 22:15:12 +000098 tst_brkm(TFAIL, cleanup, "Fork Failed");
Wanlong Gao4aeecee2012-11-20 10:32:33 +080099 } else if (pid == 0) {
plars865695b2001-08-27 22:15:12 +0000100 /*
101 * Child:
102 * Set up to catch SIGINT. The kids will wait till a
103 * SIGINT has been received before they proceed.
104 */
robbiewd34d5812005-07-11 22:28:09 +0000105 setup_sigint();
plars865695b2001-08-27 22:15:12 +0000106
subrata_modak56207ce2009-03-23 13:35:39 +0000107 /* check for looping state if -i option is given */
108 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800109 /* reset tst_count in case we are looping */
110 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000111
subrata_modak56207ce2009-03-23 13:35:39 +0000112 intintr = 0;
plars865695b2001-08-27 22:15:12 +0000113
subrata_modak56207ce2009-03-23 13:35:39 +0000114 fail = 0;
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800115 pid = FORK_OR_VFORK();
116 if (pid < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000117 tst_brkm(TFAIL, cleanup, "Fork failed.");
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800118 } else if (pid == 0) { /* child */
robbiewd34d5812005-07-11 22:28:09 +0000119#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000120 if (self_exec(argv[0], "") < 0) {
121 tst_brkm(TFAIL, cleanup,
122 "self_exec failed");
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800123 }
robbiewd34d5812005-07-11 22:28:09 +0000124#else
subrata_modak56207ce2009-03-23 13:35:39 +0000125 do_exit();
robbiewd34d5812005-07-11 22:28:09 +0000126#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000127 } else { /* parent */
128
129 /*
130 *Check that waitpid with WNOHANG returns zero
131 */
132 while (((ret = waitpid(pid, &status, WNOHANG))
plars865695b2001-08-27 22:15:12 +0000133 != 0) || (errno == EINTR)) {
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800134 if (ret == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000135 continue;
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800136
subrata_modak56207ce2009-03-23 13:35:39 +0000137 tst_resm(TFAIL, "return value for "
138 "WNOHANG expected 0 got %d",
139 ret);
140 fail = 1;
plars865695b2001-08-27 22:15:12 +0000141 }
robbiewd34d5812005-07-11 22:28:09 +0000142#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000143 /* Give the kids a chance to setup SIGINT again, since
144 * this is cleared by exec().
145 */
146 sleep(3);
robbiewd34d5812005-07-11 22:28:09 +0000147#endif
plars865695b2001-08-27 22:15:12 +0000148
subrata_modak56207ce2009-03-23 13:35:39 +0000149 /* send SIGINT to child to tell it to proceed */
150 if (kill(pid, SIGINT) < 0) {
151 tst_resm(TFAIL, "Kill of child failed, "
152 "errno = %d", errno);
153 fail = 1;
154 }
155
156 while (((ret = waitpid(pid, &status, 0)) != -1)
157 || (errno == EINTR)) {
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800158 if (ret == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000159 continue;
subrata_modak56207ce2009-03-23 13:35:39 +0000160
161 if (ret != pid) {
162 tst_resm(TFAIL, "Expected %d "
163 "got %d as proc id of "
164 "child", pid, ret);
165 fail = 1;
166 }
167
168 if (status != 0) {
169 tst_resm(TFAIL, "status value "
170 "got %d expected 0",
171 status);
172 fail = 1;
173 }
174 }
175 }
176
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800177 pid = FORK_OR_VFORK();
178 if (pid < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000179 tst_brkm(TFAIL, cleanup, "Second fork failed.");
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800180 } else if (pid == 0) { /* child */
subrata_modak56207ce2009-03-23 13:35:39 +0000181 exit(0);
182 } else { /* parent */
183 /* Give the child time to startup and exit */
184 sleep(2);
185
186 while (((ret = waitpid(pid, &status, WNOHANG))
187 != -1) || (errno == EINTR)) {
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800188 if (ret == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000189 continue;
subrata_modak56207ce2009-03-23 13:35:39 +0000190
191 if (ret != pid) {
192 tst_resm(TFAIL, "proc id %d "
193 "and retval %d do not "
194 "match", pid, ret);
195 fail = 1;
196 }
197
198 if (status != 0) {
199 tst_resm(TFAIL, "non zero "
200 "status received %d",
201 status);
202 fail = 1;
203 }
204 }
205 }
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800206
207 if (fail)
subrata_modak56207ce2009-03-23 13:35:39 +0000208 tst_resm(TFAIL, "case 1 FAILED");
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800209 else
subrata_modak56207ce2009-03-23 13:35:39 +0000210 tst_resm(TPASS, "case 1 PASSED");
subrata_modak56207ce2009-03-23 13:35:39 +0000211
212 fail = 0;
213 ret = waitpid(pid, &status, 0);
214
215 if (ret != -1) {
216 tst_resm(TFAIL, "Expected -1 got %d", ret);
217 fail = 1;
218 }
subrata_modak56207ce2009-03-23 13:35:39 +0000219 if (errno != ECHILD) {
220 tst_resm(TFAIL, "Expected ECHILD got %d",
221 errno);
plars865695b2001-08-27 22:15:12 +0000222 fail = 1;
223 }
224
subrata_modak56207ce2009-03-23 13:35:39 +0000225 ret = waitpid(pid, &status, WNOHANG);
226 if (ret != -1) {
227 tst_resm(TFAIL, "WNOHANG: Expected -1 got %d",
228 ret);
229 fail = 1;
plars865695b2001-08-27 22:15:12 +0000230 }
subrata_modak56207ce2009-03-23 13:35:39 +0000231 if (errno != ECHILD) {
232 tst_resm(TFAIL, "WNOHANG: Expected ECHILD got "
233 "%d", errno);
234 fail = 1;
plars865695b2001-08-27 22:15:12 +0000235 }
plars865695b2001-08-27 22:15:12 +0000236
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800237 if (fail)
subrata_modak56207ce2009-03-23 13:35:39 +0000238 tst_resm(TFAIL, "case 2 FAILED");
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800239 else
subrata_modak56207ce2009-03-23 13:35:39 +0000240 tst_resm(TPASS, "case 2 PASSED");
plars865695b2001-08-27 22:15:12 +0000241 }
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800242
subrata_modak56207ce2009-03-23 13:35:39 +0000243 cleanup();
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800244 } else {
plars865695b2001-08-27 22:15:12 +0000245 /* wait for the child to return */
246 waitpid(pid, &status, 0);
247 if (WEXITSTATUS(status) != 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000248 tst_brkm(TBROK, cleanup, "child returned bad "
249 "status");
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800250 }
plars865695b2001-08-27 22:15:12 +0000251 }
robbiewaa01abd2003-03-27 18:39:24 +0000252
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800253 tst_exit();
plars865695b2001-08-27 22:15:12 +0000254}
255
256/*
robbiewd34d5812005-07-11 22:28:09 +0000257 * setup_sigint()
258 * sets up a SIGINT handler
259 */
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800260static void setup_sigint(void)
robbiewd34d5812005-07-11 22:28:09 +0000261{
subrata_modak56207ce2009-03-23 13:35:39 +0000262 if ((sig_t) signal(SIGINT, inthandlr) == SIG_ERR) {
robbiewd34d5812005-07-11 22:28:09 +0000263 tst_brkm(TFAIL, cleanup, "signal SIGINT failed, errno = %d",
264 errno);
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800265 }
robbiewd34d5812005-07-11 22:28:09 +0000266}
267
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800268static void setup(void)
plars865695b2001-08-27 22:15:12 +0000269{
plars865695b2001-08-27 22:15:12 +0000270 TEST_PAUSE;
271}
272
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800273static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000274{
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800275}
plars865695b2001-08-27 22:15:12 +0000276
Mike Frysingerc57fba52014-04-09 18:56:30 -0400277static void inthandlr(void)
plars865695b2001-08-27 22:15:12 +0000278{
279 intintr++;
280}
281
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800282static void wait_for_parent(void)
plars865695b2001-08-27 22:15:12 +0000283{
284 int testvar;
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800285 while (!intintr)
plars865695b2001-08-27 22:15:12 +0000286 testvar = 0;
plars865695b2001-08-27 22:15:12 +0000287}
288
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800289static void do_exit(void)
plars865695b2001-08-27 22:15:12 +0000290{
291 wait_for_parent();
292 exit(0);
293}
robbiewd34d5812005-07-11 22:28:09 +0000294
295#ifdef UCLINUX
296/*
297 * do_exit_uclinux()
298 * Sets up SIGINT handler again, then calls do_exit
299 */
Wanlong Gao4aeecee2012-11-20 10:32:33 +0800300static void do_exit_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000301{
302 setup_sigint();
303 do_exit();
304}
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800305#endif