]> git.ipfire.org Git - thirdparty/glibc.git/blame - posix/tst-waitid.c
Add some spaces before '('.
[thirdparty/glibc.git] / posix / tst-waitid.c
CommitLineData
43300667 1/* Tests for waitid.
04277e02 2 Copyright (C) 2004-2019 Free Software Foundation, Inc.
43300667
RM
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library 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 the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
43300667
RM
18
19#include <errno.h>
bb677c95 20#include <stdio.h>
43300667
RM
21#include <stdlib.h>
22#include <unistd.h>
23#include <sys/wait.h>
24#include <signal.h>
25
43300667
RM
26static void
27test_child (void)
28{
f9e1a251
RM
29 /* Wait a second to be sure the parent set his variables before we
30 produce a SIGCHLD. */
31 sleep (1);
32
43300667
RM
33 /* First thing, we stop ourselves. */
34 raise (SIGSTOP);
35
36 /* Hey, we got continued! */
37 while (1)
38 pause ();
39}
40
41#ifndef WEXITED
42# define WEXITED 0
43# define WCONTINUED 0
44# define WSTOPPED WUNTRACED
45#endif
46
f9e1a251
RM
47static sig_atomic_t expecting_sigchld, spurious_sigchld;
48#ifdef SA_SIGINFO
49static siginfo_t sigchld_info;
50
51static void
52sigchld (int signo, siginfo_t *info, void *ctx)
53{
54 if (signo != SIGCHLD)
55 {
bb677c95 56 printf ("SIGCHLD handler got signal %d instead!\n", signo);
f9e1a251
RM
57 _exit (EXIT_FAILURE);
58 }
59
60 if (! expecting_sigchld)
61 {
62 spurious_sigchld = 1;
bb677c95
UD
63 printf ("spurious SIGCHLD: signo %d code %d status %d pid %d\n",
64 info->si_signo, info->si_code, info->si_status, info->si_pid);
f9e1a251
RM
65 }
66 else
67 {
68 sigchld_info = *info;
69 expecting_sigchld = 0;
70 }
71}
72
73static void
74check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid)
75{
76 if (expecting_sigchld)
77 {
bb677c95 78 printf ("missing SIGCHLD on %s\n", phase);
f9e1a251
RM
79 *ok = EXIT_FAILURE;
80 expecting_sigchld = 0;
81 return;
82 }
83
84 if (sigchld_info.si_signo != SIGCHLD)
85 {
bb677c95 86 printf ("SIGCHLD for %s signal %d\n", phase, sigchld_info.si_signo);
f9e1a251
RM
87 *ok = EXIT_FAILURE;
88 }
89 if (sigchld_info.si_code != code)
90 {
bb677c95 91 printf ("SIGCHLD for %s code %d\n", phase, sigchld_info.si_code);
f9e1a251
RM
92 *ok = EXIT_FAILURE;
93 }
94 if (sigchld_info.si_status != status)
95 {
bb677c95 96 printf ("SIGCHLD for %s status %d\n", phase, sigchld_info.si_status);
f9e1a251
RM
97 *ok = EXIT_FAILURE;
98 }
99 if (sigchld_info.si_pid != pid)
100 {
bb677c95 101 printf ("SIGCHLD for %s pid %d\n", phase, sigchld_info.si_pid);
f9e1a251
RM
102 *ok = EXIT_FAILURE;
103 }
104}
105# define CHECK_SIGCHLD(phase, code_check, status_check) \
106 check_sigchld ((phase), &status, (code_check), (status_check), pid)
107#else
108# define CHECK_SIGCHLD(phase, code, status) ((void) 0)
109#endif
110
43300667
RM
111static int
112do_test (int argc, char *argv[])
113{
f9e1a251
RM
114#ifdef SA_SIGINFO
115 struct sigaction sa;
116 sa.sa_flags = SA_SIGINFO|SA_RESTART;
117 sa.sa_sigaction = &sigchld;
118 if (sigemptyset (&sa.sa_mask) < 0 || sigaction (SIGCHLD, &sa, NULL) < 0)
119 {
bb677c95 120 printf ("setting SIGCHLD handler: %m\n");
f9e1a251
RM
121 return EXIT_FAILURE;
122 }
123#endif
124
125 expecting_sigchld = 1;
126
43300667
RM
127 pid_t pid = fork ();
128 if (pid < 0)
129 {
bb677c95 130 printf ("fork: %m\n");
43300667
RM
131 return EXIT_FAILURE;
132 }
133 else if (pid == 0)
134 {
135 test_child ();
136 _exit (127);
137 }
138
44219bd9 139 int status = EXIT_SUCCESS;
f9e1a251
RM
140#define RETURN(ok) \
141 do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0)
44219bd9 142
43300667 143 /* Give the child a chance to stop. */
f9e1a251
RM
144 sleep (3);
145
a58ad3f8 146 CHECK_SIGCHLD ("stopped (before waitid)", CLD_STOPPED, SIGSTOP);
43300667
RM
147
148 /* Now try a wait that should not succeed. */
149 siginfo_t info;
150 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
151 int fail = waitid (P_PID, pid, &info, WEXITED|WCONTINUED|WNOHANG);
152 switch (fail)
153 {
154 default:
bb677c95 155 printf ("waitid returned bogus value %d\n", fail);
44219bd9 156 RETURN (EXIT_FAILURE);
43300667 157 case -1:
bb677c95 158 printf ("waitid WNOHANG on stopped: %m\n");
44219bd9 159 RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
43300667
RM
160 case 0:
161 if (info.si_signo == 0)
162 break;
163 if (info.si_signo == SIGCHLD)
bb677c95 164 printf ("waitid WNOHANG on stopped status %d\n", info.si_status);
43300667 165 else
bb677c95 166 printf ("waitid WNOHANG on stopped signal %d\n", info.si_signo);
44219bd9 167 RETURN (EXIT_FAILURE);
43300667
RM
168 }
169
170 /* Next the wait that should succeed right away. */
171 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
172 info.si_pid = -1;
173 info.si_status = -1;
174 fail = waitid (P_PID, pid, &info, WSTOPPED|WNOHANG);
175 switch (fail)
176 {
177 default:
bb677c95 178 printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail);
44219bd9 179 RETURN (EXIT_FAILURE);
43300667 180 case -1:
bb677c95 181 printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n");
44219bd9 182 RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
43300667
RM
183 case 0:
184 if (info.si_signo != SIGCHLD)
185 {
bb677c95
UD
186 printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n",
187 info.si_signo);
44219bd9 188 RETURN (EXIT_FAILURE);
43300667
RM
189 }
190 if (info.si_code != CLD_STOPPED)
191 {
bb677c95
UD
192 printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n",
193 info.si_code);
44219bd9 194 RETURN (EXIT_FAILURE);
43300667
RM
195 }
196 if (info.si_status != SIGSTOP)
197 {
bb677c95
UD
198 printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n",
199 info.si_status);
44219bd9 200 RETURN (EXIT_FAILURE);
43300667
RM
201 }
202 if (info.si_pid != pid)
203 {
bb677c95
UD
204 printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
205 info.si_pid, pid);
44219bd9 206 RETURN (EXIT_FAILURE);
43300667
RM
207 }
208 }
209
f9e1a251
RM
210 expecting_sigchld = WCONTINUED != 0;
211
43300667
RM
212 if (kill (pid, SIGCONT) != 0)
213 {
bb677c95 214 printf ("kill (%d, SIGCONT): %m\n", pid);
44219bd9 215 RETURN (EXIT_FAILURE);
43300667
RM
216 }
217
218 /* Wait for the child to have continued. */
219 sleep (2);
220
44219bd9 221#if WCONTINUED != 0
f9e1a251
RM
222 if (expecting_sigchld)
223 {
bb677c95 224 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
f9e1a251
RM
225 expecting_sigchld = 0;
226 }
227 else
a58ad3f8 228 CHECK_SIGCHLD ("continued (before waitid)", CLD_CONTINUED, SIGCONT);
f9e1a251
RM
229
230 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
231 info.si_pid = -1;
232 info.si_status = -1;
233 fail = waitid (P_PID, pid, &info, WCONTINUED|WNOWAIT);
234 switch (fail)
235 {
236 default:
bb677c95 237 printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail);
f9e1a251
RM
238 RETURN (EXIT_FAILURE);
239 case -1:
bb677c95 240 printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n");
f9e1a251
RM
241 RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
242 case 0:
243 if (info.si_signo != SIGCHLD)
244 {
bb677c95
UD
245 printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n",
246 info.si_signo);
f9e1a251
RM
247 RETURN (EXIT_FAILURE);
248 }
249 if (info.si_code != CLD_CONTINUED)
250 {
bb677c95
UD
251 printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n",
252 info.si_code);
f9e1a251
RM
253 RETURN (EXIT_FAILURE);
254 }
255 if (info.si_status != SIGCONT)
256 {
bb677c95
UD
257 printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n",
258 info.si_status);
f9e1a251
RM
259 RETURN (EXIT_FAILURE);
260 }
261 if (info.si_pid != pid)
262 {
bb677c95
UD
263 printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
264 info.si_pid, pid);
f9e1a251
RM
265 RETURN (EXIT_FAILURE);
266 }
267 }
268
269 /* That should leave the CLD_CONTINUED state waiting to be seen again. */
43300667
RM
270 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
271 info.si_pid = -1;
272 info.si_status = -1;
273 fail = waitid (P_PID, pid, &info, WCONTINUED);
274 switch (fail)
275 {
276 default:
bb677c95 277 printf ("waitid WCONTINUED returned bogus value %d\n", fail);
44219bd9 278 RETURN (EXIT_FAILURE);
43300667 279 case -1:
bb677c95 280 printf ("waitid WCONTINUED on continued: %m\n");
44219bd9 281 RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
43300667
RM
282 case 0:
283 if (info.si_signo != SIGCHLD)
284 {
bb677c95 285 printf ("waitid WCONTINUED on continued signal %d\n", info.si_signo);
44219bd9 286 RETURN (EXIT_FAILURE);
43300667
RM
287 }
288 if (info.si_code != CLD_CONTINUED)
289 {
bb677c95 290 printf ("waitid WCONTINUED on continued code %d\n", info.si_code);
44219bd9 291 RETURN (EXIT_FAILURE);
43300667
RM
292 }
293 if (info.si_status != SIGCONT)
294 {
bb677c95
UD
295 printf ("waitid WCONTINUED on continued status %d\n",
296 info.si_status);
44219bd9 297 RETURN (EXIT_FAILURE);
43300667
RM
298 }
299 if (info.si_pid != pid)
300 {
bb677c95
UD
301 printf ("waitid WCONTINUED on continued pid %d != %d\n",
302 info.si_pid, pid);
44219bd9 303 RETURN (EXIT_FAILURE);
43300667
RM
304 }
305 }
f9e1a251
RM
306
307 /* Now try a wait that should not succeed. */
308 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
309 fail = waitid (P_PID, pid, &info, WCONTINUED|WNOHANG);
310 switch (fail)
311 {
312 default:
bb677c95 313 printf ("waitid returned bogus value %d\n", fail);
f9e1a251
RM
314 RETURN (EXIT_FAILURE);
315 case -1:
bb677c95 316 printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n");
f9e1a251
RM
317 RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
318 case 0:
319 if (info.si_signo == 0)
320 break;
321 if (info.si_signo == SIGCHLD)
bb677c95
UD
322 printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n",
323 info.si_status);
f9e1a251 324 else
bb677c95
UD
325 printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
326 info.si_signo);
f9e1a251
RM
327 RETURN (EXIT_FAILURE);
328 }
a044c713
RM
329
330 /* Now stop him again and test waitpid with WCONTINUED. */
331 expecting_sigchld = 1;
332 if (kill (pid, SIGSTOP) != 0)
333 {
bb677c95 334 printf ("kill (%d, SIGSTOP): %m\n", pid);
a044c713
RM
335 RETURN (EXIT_FAILURE);
336 }
a58ad3f8
RM
337
338 /* Give the child a chance to stop. The waitpid call below will block
339 until it has stopped, but if we are real quick and enter the waitpid
340 system call before the SIGCHLD has been generated, then it will be
341 discarded and never delivered. */
342 sleep (3);
343
a044c713
RM
344 pid_t wpid = waitpid (pid, &fail, WUNTRACED);
345 if (wpid < 0)
346 {
bb677c95 347 printf ("waitpid WUNTRACED on stopped: %m\n");
a044c713
RM
348 RETURN (EXIT_FAILURE);
349 }
350 else if (wpid != pid)
351 {
bb677c95
UD
352 printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n",
353 wpid, pid, fail);
a044c713
RM
354 RETURN (EXIT_FAILURE);
355 }
356 else if (!WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail)
357 || WIFCONTINUED (fail) || WSTOPSIG (fail) != SIGSTOP)
358 {
bb677c95 359 printf ("waitpid WUNTRACED on stopped: status %x\n", fail);
a044c713
RM
360 RETURN (EXIT_FAILURE);
361 }
a58ad3f8 362 CHECK_SIGCHLD ("stopped (after waitpid)", CLD_STOPPED, SIGSTOP);
a044c713
RM
363
364 expecting_sigchld = 1;
365 if (kill (pid, SIGCONT) != 0)
366 {
bb677c95 367 printf ("kill (%d, SIGCONT): %m\n", pid);
a044c713
RM
368 RETURN (EXIT_FAILURE);
369 }
370
371 /* Wait for the child to have continued. */
372 sleep (2);
373
374 if (expecting_sigchld)
375 {
bb677c95 376 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
a044c713
RM
377 expecting_sigchld = 0;
378 }
379 else
a58ad3f8 380 CHECK_SIGCHLD ("continued (before waitpid)", CLD_CONTINUED, SIGCONT);
a044c713
RM
381
382 wpid = waitpid (pid, &fail, WCONTINUED);
383 if (wpid < 0)
384 {
385 if (errno == EINVAL)
bb677c95 386 printf ("waitpid does not support WCONTINUED\n");
a044c713
RM
387 else
388 {
bb677c95 389 printf ("waitpid WCONTINUED on continued: %m\n");
a044c713
RM
390 RETURN (EXIT_FAILURE);
391 }
392 }
393 else if (wpid != pid)
394 {
bb677c95
UD
395 printf ("\
396waitpid WCONTINUED on continued returned %d != %d (status %x)\n",
a044c713
RM
397 wpid, pid, fail);
398 RETURN (EXIT_FAILURE);
399 }
400 else if (WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail)
401 || !WIFCONTINUED (fail))
402 {
bb677c95 403 printf ("waitpid WCONTINUED on continued: status %x\n", fail);
a044c713
RM
404 RETURN (EXIT_FAILURE);
405 }
43300667
RM
406#endif
407
f9e1a251
RM
408 expecting_sigchld = 1;
409
43300667
RM
410 /* Die, child, die! */
411 if (kill (pid, SIGKILL) != 0)
412 {
bb677c95 413 printf ("kill (%d, SIGKILL): %m\n", pid);
44219bd9 414 RETURN (EXIT_FAILURE);
43300667
RM
415 }
416
417#ifdef WNOWAIT
418 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
419 info.si_pid = -1;
420 info.si_status = -1;
421 fail = waitid (P_PID, pid, &info, WEXITED|WNOWAIT);
422 switch (fail)
423 {
424 default:
bb677c95 425 printf ("waitid WNOWAIT returned bogus value %d\n", fail);
44219bd9 426 RETURN (EXIT_FAILURE);
43300667 427 case -1:
bb677c95 428 printf ("waitid WNOWAIT on killed: %m\n");
44219bd9 429 RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
43300667
RM
430 case 0:
431 if (info.si_signo != SIGCHLD)
432 {
bb677c95 433 printf ("waitid WNOWAIT on killed signal %d\n", info.si_signo);
44219bd9 434 RETURN (EXIT_FAILURE);
43300667
RM
435 }
436 if (info.si_code != CLD_KILLED)
437 {
bb677c95 438 printf ("waitid WNOWAIT on killed code %d\n", info.si_code);
44219bd9 439 RETURN (EXIT_FAILURE);
43300667
RM
440 }
441 if (info.si_status != SIGKILL)
442 {
bb677c95 443 printf ("waitid WNOWAIT on killed status %d\n", info.si_status);
44219bd9 444 RETURN (EXIT_FAILURE);
43300667
RM
445 }
446 if (info.si_pid != pid)
447 {
bb677c95 448 printf ("waitid WNOWAIT on killed pid %d != %d\n", info.si_pid, pid);
44219bd9 449 RETURN (EXIT_FAILURE);
43300667
RM
450 }
451 }
452#else
453 /* Allow enough time to be sure the child died; we didn't synchronize. */
454 sleep (2);
455#endif
456
f9e1a251
RM
457 CHECK_SIGCHLD ("killed", CLD_KILLED, SIGKILL);
458
43300667
RM
459 info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
460 info.si_pid = -1;
461 info.si_status = -1;
462 fail = waitid (P_PID, pid, &info, WEXITED|WNOHANG);
463 switch (fail)
464 {
465 default:
bb677c95 466 printf ("waitid WNOHANG returned bogus value %d\n", fail);
44219bd9 467 RETURN (EXIT_FAILURE);
43300667 468 case -1:
bb677c95 469 printf ("waitid WNOHANG on killed: %m\n");
44219bd9 470 RETURN (EXIT_FAILURE);
43300667
RM
471 case 0:
472 if (info.si_signo != SIGCHLD)
473 {
bb677c95 474 printf ("waitid WNOHANG on killed signal %d\n", info.si_signo);
44219bd9 475 RETURN (EXIT_FAILURE);
43300667
RM
476 }
477 if (info.si_code != CLD_KILLED)
478 {
bb677c95 479 printf ("waitid WNOHANG on killed code %d\n", info.si_code);
44219bd9 480 RETURN (EXIT_FAILURE);
43300667
RM
481 }
482 if (info.si_status != SIGKILL)
483 {
bb677c95 484 printf ("waitid WNOHANG on killed status %d\n", info.si_status);
44219bd9 485 RETURN (EXIT_FAILURE);
43300667
RM
486 }
487 if (info.si_pid != pid)
488 {
bb677c95 489 printf ("waitid WNOHANG on killed pid %d != %d\n", info.si_pid, pid);
44219bd9 490 RETURN (EXIT_FAILURE);
43300667
RM
491 }
492 }
493
494 fail = waitid (P_PID, pid, &info, WEXITED);
495 if (fail == -1)
496 {
497 if (errno != ECHILD)
498 {
bb677c95 499 printf ("waitid WEXITED on killed: %m\n");
44219bd9 500 RETURN (EXIT_FAILURE);
43300667
RM
501 }
502 }
503 else
504 {
bb677c95 505 printf ("waitid WEXITED returned bogus value %d\n", fail);
44219bd9 506 RETURN (EXIT_FAILURE);
43300667
RM
507 }
508
44219bd9
RM
509#undef RETURN
510 out:
f9e1a251
RM
511 if (spurious_sigchld)
512 status = EXIT_FAILURE;
47544448 513 signal (SIGCHLD, SIG_IGN);
44219bd9
RM
514 kill (pid, SIGKILL); /* Make sure it's dead if we bailed early. */
515 return status;
43300667
RM
516}
517
518#include "../test-skeleton.c"