1 /*
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
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * waitpid03.c
23 *
24 * DESCRIPTION
25 * Check that parent waits unitl specific child has returned.
26 *
27 * ALGORITHM
28 * Parent forks numerous (22 = MAXUPRC - 3) children, and starts waits :
29 * Should only wait for the specific child, a second wait on the same
30 * child should return with -1 and not one of the other zombied
31 * children.
32 *
33 * USAGE: <for command-line>
34 * waitpid03 [-c n] [-i n] [-I x] [-P x] [-t]
35 * where, -c n : Run n copies concurrently.
36 * -i n : Execute test n times.
37 * -I x : Execute test for x seconds.
38 * -P x : Pause for x seconds between iterations.
39 * -t : Turn on syscall timing.
40 *
41 * History
42 * 07/2001 John George
43 * -Ported
44 * 04/2002 wjhuie sigset cleanups
45 *
46 * Restrictions
47 * None
48 */
49
50 #define DEBUG 0
51
52 #include <sys/types.h>
53 #include <signal.h>
54 #include <errno.h>
55 #include <sys/wait.h>
56 #include "test.h"
57
58 static void do_child(int);
59 static void setup(void);
60 static void cleanup(void);
61
62 char *TCID = "waitpid03";
63 int TST_TOTAL = 1;
64
65 #define MAXUPRC 25
66
67 static int ikids;
68 static int pid[MAXUPRC];
69 static int condition_number;
70
71 #ifdef UCLINUX
72 static void do_child_uclinux(void);
73 static int ikids_uclinux;
74 #endif
75
main(int argc,char ** argv)76 int main(int argc, char **argv)
77 {
78 int lc;
79
80 int status, ret;
81
82 tst_parse_opts(argc, argv, NULL, NULL);
83 #ifdef UCLINUX
84 maybe_run_child(&do_child, "d", &ikids_uclinux);
85 #endif
86
87 setup();
88
89 /* check for looping state if -i option is given */
90 for (lc = 0; TEST_LOOPING(lc); lc++) {
91 /* reset tst_count in case we are looping */
92 tst_count = 0;
93
94 /*
95 * Set SIGTERM to SIG_DFL as test driver sets up to ignore
96 * SIGTERM
97 */
98 if ((sig_t) signal(SIGTERM, SIG_DFL) == SIG_ERR) {
99 tst_resm(TFAIL, "Signal SIGTERM failed, errno = %d",
100 errno);
101
102 }
103
104 while (++ikids < MAXUPRC) {
105 pid[ikids] = FORK_OR_VFORK();
106 if (pid[ikids] > 0) {
107 if (DEBUG)
108 tst_resm(TINFO, "child # %d", ikids);
109 } else if (pid[ikids] == -1) {
110 tst_brkm(TBROK|TERRNO, cleanup, "cannot open "
111 "fork #%d", ikids);
112
113 } else {
114 #ifdef UCLINUX
115 if (self_exec(argv[0], "d", ikids) < 0) {
116 tst_resm(TFAIL, "cannot self_exec #%d",
117 ikids);
118 }
119 #else
120 do_child(ikids);
121 #endif
122 }
123 }
124
125 for (ikids = 1; ikids < MAXUPRC; ikids++) {
126 if (DEBUG)
127 tst_resm(TINFO, "Killing #%d", ikids);
128 kill(pid[ikids], SIGTERM);
129 }
130
131 ikids = 0;
132 condition_number = 1;
133
134 /* Wait on one specific child */
135 if (DEBUG)
136 tst_resm(TINFO, "Waiting for child:#%d", MAXUPRC / 2);
137 ret = waitpid(pid[MAXUPRC / 2], &status, 0);
138 if (ret != pid[MAXUPRC / 2]) {
139 tst_resm(TFAIL, "condition %d test failed. "
140 "waitpid(%d) returned %d.",
141 condition_number, pid[MAXUPRC / 2], ret);
142 } else {
143 tst_resm(TPASS, "Got correct child PID");
144 }
145 condition_number++;
146
147 /*
148 * Child has already been waited on, waitpid should return
149 * -1
150 */
151 ret = waitpid(pid[MAXUPRC / 2], &status, 0);
152 if (ret != -1) {
153 tst_resm(TFAIL, "condition %d test failed",
154 condition_number);
155 } else {
156 tst_resm(TPASS, "Condition %d test passed",
157 condition_number);
158 }
159 condition_number++;
160 }
161
162 cleanup();
163 tst_exit();
164 }
165
do_child(int ikids)166 static void do_child(int ikids)
167 {
168 if (DEBUG)
169 tst_resm(TINFO, "child:%d", ikids);
170 pause();
171 exit(0);
172 }
173
174 #ifdef UCLINUX
175 /*
176 * do_child_uclinux()
177 * run do_child with the appropriate ikids variable
178 */
do_child_uclinux(void)179 static void do_child_uclinux(void)
180 {
181 do_child(ikids_uclinux);
182 }
183 #endif
184
setup(void)185 static void setup(void)
186 {
187 TEST_PAUSE;
188 }
189
cleanup(void)190 static void cleanup(void)
191 {
192 while (ikids-- > 1)
193 kill(pid[ikids], SIGKILL);
194 }
195