/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- wait_badpid
- wait_badstatus
- wait_unaligned
- wait_badflags
- wait_self
- wait_parent
- wait_siblings_child
- wait_siblings
- test_waitpid
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3 * The President and Fellows of Harvard College.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * bad calls to waitpid()
32 */
33
34 #include <sys/types.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <err.h>
39
40 #include "config.h"
41 #include "test.h"
42
43 static
44 void
45 wait_badpid(int pid, const char *desc)
46 {
47 int rv, x;
48 rv = waitpid(pid, &x, 0);
49 report_test2(rv, errno, EINVAL, NOSUCHPID_ERROR, desc);
50 }
51
52 static
53 void
54 wait_badstatus(void *ptr, const char *desc)
55 {
56 int rv, pid, x;
57
58 pid = fork();
59 if (pid<0) {
60 warn("UH-OH: fork failed");
61 return;
62 }
63 if (pid==0) {
64 exit(0);
65 }
66
67 rv = waitpid(pid, ptr, 0);
68 report_test(rv, errno, EFAULT, desc);
69 waitpid(pid, &x, 0);
70 }
71
72 static
73 void
74 wait_unaligned(void)
75 {
76 int rv, pid, x;
77 int status[2]; /* will have integer alignment */
78 char *ptr;
79
80 pid = fork();
81 if (pid<0) {
82 warn("UH-OH: fork failed");
83 return;
84 }
85 if (pid==0) {
86 exit(0);
87 }
88
89 /* start with proper integer alignment */
90 ptr = (char *)(&status[0]);
91
92 /* generate improper alignment on platforms with restrictions*/
93 ptr++;
94
95 rv = waitpid(pid, (int *)ptr, 0);
96 report_survival(rv, errno, "wait with unaligned status");
97 if (rv<0) {
98 waitpid(pid, &x, 0);
99 }
100 }
101
102 static
103 void
104 wait_badflags(void)
105 {
106 int rv, x, pid;
107
108 pid = fork();
109 if (pid<0) {
110 warn("UH-OH: fork failed");
111 return;
112 }
113 if (pid==0) {
114 exit(0);
115 }
116
117 rv = waitpid(pid, &x, 309429);
118 report_test(rv, errno, EINVAL, "wait with bad flags");
119 waitpid(pid, &x, 0);
120 }
121
122 static
123 void
124 wait_self(void)
125 {
126 int rv, x;
127 rv = waitpid(getpid(), &x, 0);
128 report_survival(rv, errno, "wait for self");
129 }
130
131 static
132 void
133 wait_parent(void)
134 {
135 int mypid, childpid, rv, x;
136
137 mypid = getpid();
138 childpid = fork();
139 if (childpid<0) {
140 warn("UH-OH: can't fork");
141 return;
142 }
143 if (childpid==0) {
144 /* Child. Wait for parent. */
145 rv = waitpid(mypid, &x, 0);
146 report_survival(rv, errno, "wait for parent (from child)");
147 _exit(0);
148 }
149 rv = waitpid(childpid, &x, 0);
150 report_survival(rv, errno, "wait for parent test (from parent)");
151 }
152
153 ////////////////////////////////////////////////////////////
154
155 static
156 void
157 wait_siblings_child(void)
158 {
159 int pids[2], mypid, otherpid, fd, rv, x;
160
161 mypid = getpid();
162
163 fd = open(TESTFILE, O_RDONLY);
164 if (fd<0) {
165 warn("UH-OH: child process (pid %d) can't open %s",
166 mypid, TESTFILE);
167 return;
168 }
169
170 /*
171 * Busy-wait until the parent writes the pids into the file.
172 * This sucks, but there's not a whole lot else we can do.
173 */
174 do {
175 rv = lseek(fd, 0, SEEK_SET);
176 if (rv<0) {
177 warn("UH-OH: child process (pid %d) lseek error",
178 mypid);
179 return;
180 }
181 rv = read(fd, pids, sizeof(pids));
182 if (rv<0) {
183 warn("UH-OH: child process (pid %d) read error",
184 mypid);
185 return;
186 }
187 } while (rv < (int)sizeof(pids));
188
189 if (mypid==pids[0]) {
190 otherpid = pids[1];
191 }
192 else if (mypid==pids[1]) {
193 otherpid = pids[0];
194 }
195 else {
196 warn("UH-OH: child process (pid %d) got garbage in comm file",
197 mypid);
198 return;
199 }
200 close(fd);
201
202 rv = waitpid(otherpid, &x, 0);
203 report_survival(rv, errno, "sibling wait");
204 }
205
206 static
207 void
208 wait_siblings(void)
209 {
210 int pids[2], fd, rv, x;
211
212 /* Note: this may also blow up if FS synchronization is substandard */
213
214 fd = open_testfile(NULL);
215 if (fd<0) {
216 return;
217 }
218
219 pids[0] = fork();
220 if (pids[0]<0) {
221 warn("UH-OH: can't fork");
222 return;
223 }
224 if (pids[0]==0) {
225 close(fd);
226 wait_siblings_child();
227 _exit(0);
228 }
229
230 pids[1] = fork();
231 if (pids[1]<0) {
232 warn("UH-OH: can't fork");
233 /* abandon the other child process :( */
234 return;
235 }
236 if (pids[1]==0) {
237 close(fd);
238 wait_siblings_child();
239 _exit(0);
240 }
241
242 rv = write(fd, pids, sizeof(pids));
243 if (rv < 0) {
244 warn("UH-OH: write error on %s", TESTFILE);
245 /* abandon child procs :( */
246 return;
247 }
248 if (rv != (int)sizeof(pids)) {
249 warnx("UH-OH: write error on %s: short count", TESTFILE);
250 /* abandon child procs :( */
251 return;
252 }
253
254 rv = waitpid(pids[0], &x, 0);
255 if (rv<0) {
256 warn("UH-OH: error waiting for child 0 (pid %d)", pids[0]);
257 }
258 rv = waitpid(pids[1], &x, 0);
259 if (rv<0) {
260 warn("UH-OH: error waiting for child 1 (pid %d)", pids[1]);
261 }
262 warnx("passed: siblings wait for each other");
263 close(fd);
264 remove(TESTFILE);
265 }
266
267 ////////////////////////////////////////////////////////////
268
269 void
270 test_waitpid(void)
271 {
272 wait_badpid(-8, "wait for pid -8");
273 wait_badpid(-1, "wait for pid -1");
274 wait_badpid(0, "pid zero");
275 wait_badpid(NONEXIST_PID, "nonexistent pid");
276
277 wait_badstatus(NULL, "wait with NULL status");
278 wait_badstatus(INVAL_PTR, "wait with invalid pointer status");
279 wait_badstatus(KERN_PTR, "wait with kernel pointer status");
280
281 wait_unaligned();
282
283 wait_badflags();
284
285 wait_self();
286 wait_parent();
287 wait_siblings();
288 }