2 Copyright (C) 2004-2013 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
31 /* Wait a second to be sure the parent set his variables before we
35 /* First thing, we stop ourselves. */
38 /* Hey, we got continued! */
46 # define WSTOPPED WUNTRACED
49 static sig_atomic_t expecting_sigchld
, spurious_sigchld
;
51 static siginfo_t sigchld_info
;
54 sigchld (int signo
, siginfo_t
*info
, void *ctx
)
58 printf ("SIGCHLD handler got signal %d instead!\n", signo
);
62 if (! expecting_sigchld
)
65 printf ("spurious SIGCHLD: signo %d code %d status %d pid %d\n",
66 info
->si_signo
, info
->si_code
, info
->si_status
, info
->si_pid
);
71 expecting_sigchld
= 0;
76 check_sigchld (const char *phase
, int *ok
, int code
, int status
, pid_t pid
)
78 if (expecting_sigchld
)
80 printf ("missing SIGCHLD on %s\n", phase
);
82 expecting_sigchld
= 0;
86 if (sigchld_info
.si_signo
!= SIGCHLD
)
88 printf ("SIGCHLD for %s signal %d\n", phase
, sigchld_info
.si_signo
);
91 if (sigchld_info
.si_code
!= code
)
93 printf ("SIGCHLD for %s code %d\n", phase
, sigchld_info
.si_code
);
96 if (sigchld_info
.si_status
!= status
)
98 printf ("SIGCHLD for %s status %d\n", phase
, sigchld_info
.si_status
);
101 if (sigchld_info
.si_pid
!= pid
)
103 printf ("SIGCHLD for %s pid %d\n", phase
, sigchld_info
.si_pid
);
107 # define CHECK_SIGCHLD(phase, code_check, status_check) \
108 check_sigchld ((phase), &status, (code_check), (status_check), pid)
110 # define CHECK_SIGCHLD(phase, code, status) ((void) 0)
114 do_test (int argc
, char *argv
[])
118 sa
.sa_flags
= SA_SIGINFO
|SA_RESTART
;
119 sa
.sa_sigaction
= &sigchld
;
120 if (sigemptyset (&sa
.sa_mask
) < 0 || sigaction (SIGCHLD
, &sa
, NULL
) < 0)
122 printf ("setting SIGCHLD handler: %m\n");
127 expecting_sigchld
= 1;
132 printf ("fork: %m\n");
141 int status
= EXIT_SUCCESS
;
143 do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0)
145 /* Give the child a chance to stop. */
148 CHECK_SIGCHLD ("stopped (before waitid)", CLD_STOPPED
, SIGSTOP
);
150 /* Now try a wait that should not succeed. */
152 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
153 int fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WCONTINUED
|WNOHANG
);
157 printf ("waitid returned bogus value %d\n", fail
);
158 RETURN (EXIT_FAILURE
);
160 printf ("waitid WNOHANG on stopped: %m\n");
161 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
163 if (info
.si_signo
== 0)
165 if (info
.si_signo
== SIGCHLD
)
166 printf ("waitid WNOHANG on stopped status %d\n", info
.si_status
);
168 printf ("waitid WNOHANG on stopped signal %d\n", info
.si_signo
);
169 RETURN (EXIT_FAILURE
);
172 /* Next the wait that should succeed right away. */
173 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
176 fail
= waitid (P_PID
, pid
, &info
, WSTOPPED
|WNOHANG
);
180 printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail
);
181 RETURN (EXIT_FAILURE
);
183 printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n");
184 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
186 if (info
.si_signo
!= SIGCHLD
)
188 printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n",
190 RETURN (EXIT_FAILURE
);
192 if (info
.si_code
!= CLD_STOPPED
)
194 printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n",
196 RETURN (EXIT_FAILURE
);
198 if (info
.si_status
!= SIGSTOP
)
200 printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n",
202 RETURN (EXIT_FAILURE
);
204 if (info
.si_pid
!= pid
)
206 printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
208 RETURN (EXIT_FAILURE
);
212 expecting_sigchld
= WCONTINUED
!= 0;
214 if (kill (pid
, SIGCONT
) != 0)
216 printf ("kill (%d, SIGCONT): %m\n", pid
);
217 RETURN (EXIT_FAILURE
);
220 /* Wait for the child to have continued. */
224 if (expecting_sigchld
)
226 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
227 expecting_sigchld
= 0;
230 CHECK_SIGCHLD ("continued (before waitid)", CLD_CONTINUED
, SIGCONT
);
232 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
235 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
|WNOWAIT
);
239 printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail
);
240 RETURN (EXIT_FAILURE
);
242 printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n");
243 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
245 if (info
.si_signo
!= SIGCHLD
)
247 printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n",
249 RETURN (EXIT_FAILURE
);
251 if (info
.si_code
!= CLD_CONTINUED
)
253 printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n",
255 RETURN (EXIT_FAILURE
);
257 if (info
.si_status
!= SIGCONT
)
259 printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n",
261 RETURN (EXIT_FAILURE
);
263 if (info
.si_pid
!= pid
)
265 printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
267 RETURN (EXIT_FAILURE
);
271 /* That should leave the CLD_CONTINUED state waiting to be seen again. */
272 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
275 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
);
279 printf ("waitid WCONTINUED returned bogus value %d\n", fail
);
280 RETURN (EXIT_FAILURE
);
282 printf ("waitid WCONTINUED on continued: %m\n");
283 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
285 if (info
.si_signo
!= SIGCHLD
)
287 printf ("waitid WCONTINUED on continued signal %d\n", info
.si_signo
);
288 RETURN (EXIT_FAILURE
);
290 if (info
.si_code
!= CLD_CONTINUED
)
292 printf ("waitid WCONTINUED on continued code %d\n", info
.si_code
);
293 RETURN (EXIT_FAILURE
);
295 if (info
.si_status
!= SIGCONT
)
297 printf ("waitid WCONTINUED on continued status %d\n",
299 RETURN (EXIT_FAILURE
);
301 if (info
.si_pid
!= pid
)
303 printf ("waitid WCONTINUED on continued pid %d != %d\n",
305 RETURN (EXIT_FAILURE
);
309 /* Now try a wait that should not succeed. */
310 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
311 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
|WNOHANG
);
315 printf ("waitid returned bogus value %d\n", fail
);
316 RETURN (EXIT_FAILURE
);
318 printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n");
319 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
321 if (info
.si_signo
== 0)
323 if (info
.si_signo
== SIGCHLD
)
324 printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n",
327 printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
329 RETURN (EXIT_FAILURE
);
332 /* Now stop him again and test waitpid with WCONTINUED. */
333 expecting_sigchld
= 1;
334 if (kill (pid
, SIGSTOP
) != 0)
336 printf ("kill (%d, SIGSTOP): %m\n", pid
);
337 RETURN (EXIT_FAILURE
);
340 /* Give the child a chance to stop. The waitpid call below will block
341 until it has stopped, but if we are real quick and enter the waitpid
342 system call before the SIGCHLD has been generated, then it will be
343 discarded and never delivered. */
346 pid_t wpid
= waitpid (pid
, &fail
, WUNTRACED
);
349 printf ("waitpid WUNTRACED on stopped: %m\n");
350 RETURN (EXIT_FAILURE
);
352 else if (wpid
!= pid
)
354 printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n",
356 RETURN (EXIT_FAILURE
);
358 else if (!WIFSTOPPED (fail
) || WIFSIGNALED (fail
) || WIFEXITED (fail
)
359 || WIFCONTINUED (fail
) || WSTOPSIG (fail
) != SIGSTOP
)
361 printf ("waitpid WUNTRACED on stopped: status %x\n", fail
);
362 RETURN (EXIT_FAILURE
);
364 CHECK_SIGCHLD ("stopped (after waitpid)", CLD_STOPPED
, SIGSTOP
);
366 expecting_sigchld
= 1;
367 if (kill (pid
, SIGCONT
) != 0)
369 printf ("kill (%d, SIGCONT): %m\n", pid
);
370 RETURN (EXIT_FAILURE
);
373 /* Wait for the child to have continued. */
376 if (expecting_sigchld
)
378 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
379 expecting_sigchld
= 0;
382 CHECK_SIGCHLD ("continued (before waitpid)", CLD_CONTINUED
, SIGCONT
);
384 wpid
= waitpid (pid
, &fail
, WCONTINUED
);
388 printf ("waitpid does not support WCONTINUED\n");
391 printf ("waitpid WCONTINUED on continued: %m\n");
392 RETURN (EXIT_FAILURE
);
395 else if (wpid
!= pid
)
398 waitpid WCONTINUED on continued returned %d != %d (status %x)\n",
400 RETURN (EXIT_FAILURE
);
402 else if (WIFSTOPPED (fail
) || WIFSIGNALED (fail
) || WIFEXITED (fail
)
403 || !WIFCONTINUED (fail
))
405 printf ("waitpid WCONTINUED on continued: status %x\n", fail
);
406 RETURN (EXIT_FAILURE
);
410 expecting_sigchld
= 1;
412 /* Die, child, die! */
413 if (kill (pid
, SIGKILL
) != 0)
415 printf ("kill (%d, SIGKILL): %m\n", pid
);
416 RETURN (EXIT_FAILURE
);
420 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
423 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOWAIT
);
427 printf ("waitid WNOWAIT returned bogus value %d\n", fail
);
428 RETURN (EXIT_FAILURE
);
430 printf ("waitid WNOWAIT on killed: %m\n");
431 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
433 if (info
.si_signo
!= SIGCHLD
)
435 printf ("waitid WNOWAIT on killed signal %d\n", info
.si_signo
);
436 RETURN (EXIT_FAILURE
);
438 if (info
.si_code
!= CLD_KILLED
)
440 printf ("waitid WNOWAIT on killed code %d\n", info
.si_code
);
441 RETURN (EXIT_FAILURE
);
443 if (info
.si_status
!= SIGKILL
)
445 printf ("waitid WNOWAIT on killed status %d\n", info
.si_status
);
446 RETURN (EXIT_FAILURE
);
448 if (info
.si_pid
!= pid
)
450 printf ("waitid WNOWAIT on killed pid %d != %d\n", info
.si_pid
, pid
);
451 RETURN (EXIT_FAILURE
);
455 /* Allow enough time to be sure the child died; we didn't synchronize. */
459 CHECK_SIGCHLD ("killed", CLD_KILLED
, SIGKILL
);
461 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
464 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOHANG
);
468 printf ("waitid WNOHANG returned bogus value %d\n", fail
);
469 RETURN (EXIT_FAILURE
);
471 printf ("waitid WNOHANG on killed: %m\n");
472 RETURN (EXIT_FAILURE
);
474 if (info
.si_signo
!= SIGCHLD
)
476 printf ("waitid WNOHANG on killed signal %d\n", info
.si_signo
);
477 RETURN (EXIT_FAILURE
);
479 if (info
.si_code
!= CLD_KILLED
)
481 printf ("waitid WNOHANG on killed code %d\n", info
.si_code
);
482 RETURN (EXIT_FAILURE
);
484 if (info
.si_status
!= SIGKILL
)
486 printf ("waitid WNOHANG on killed status %d\n", info
.si_status
);
487 RETURN (EXIT_FAILURE
);
489 if (info
.si_pid
!= pid
)
491 printf ("waitid WNOHANG on killed pid %d != %d\n", info
.si_pid
, pid
);
492 RETURN (EXIT_FAILURE
);
496 fail
= waitid (P_PID
, pid
, &info
, WEXITED
);
501 printf ("waitid WEXITED on killed: %m\n");
502 RETURN (EXIT_FAILURE
);
507 printf ("waitid WEXITED returned bogus value %d\n", fail
);
508 RETURN (EXIT_FAILURE
);
513 if (spurious_sigchld
)
514 status
= EXIT_FAILURE
;
515 signal (SIGCHLD
, SIG_IGN
);
516 kill (pid
, SIGKILL
); /* Make sure it's dead if we bailed early. */
520 #include "../test-skeleton.c"