2 Copyright (C) 2004 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", 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", 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
);
339 pid_t wpid
= waitpid (pid
, &fail
, WUNTRACED
);
342 printf ("waitpid WUNTRACED on stopped: %m\n");
343 RETURN (EXIT_FAILURE
);
345 else if (wpid
!= pid
)
347 printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n",
349 RETURN (EXIT_FAILURE
);
351 else if (!WIFSTOPPED (fail
) || WIFSIGNALED (fail
) || WIFEXITED (fail
)
352 || WIFCONTINUED (fail
) || WSTOPSIG (fail
) != SIGSTOP
)
354 printf ("waitpid WUNTRACED on stopped: status %x\n", fail
);
355 RETURN (EXIT_FAILURE
);
357 CHECK_SIGCHLD ("stopped", CLD_STOPPED
, SIGSTOP
);
359 expecting_sigchld
= 1;
360 if (kill (pid
, SIGCONT
) != 0)
362 printf ("kill (%d, SIGCONT): %m\n", pid
);
363 RETURN (EXIT_FAILURE
);
366 /* Wait for the child to have continued. */
369 if (expecting_sigchld
)
371 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
372 expecting_sigchld
= 0;
375 CHECK_SIGCHLD ("continued", CLD_CONTINUED
, SIGCONT
);
377 wpid
= waitpid (pid
, &fail
, WCONTINUED
);
381 printf ("waitpid does not support WCONTINUED\n");
384 printf ("waitpid WCONTINUED on continued: %m\n");
385 RETURN (EXIT_FAILURE
);
388 else if (wpid
!= pid
)
391 waitpid WCONTINUED on continued returned %d != %d (status %x)\n",
393 RETURN (EXIT_FAILURE
);
395 else if (WIFSTOPPED (fail
) || WIFSIGNALED (fail
) || WIFEXITED (fail
)
396 || !WIFCONTINUED (fail
))
398 printf ("waitpid WCONTINUED on continued: status %x\n", fail
);
399 RETURN (EXIT_FAILURE
);
403 expecting_sigchld
= 1;
405 /* Die, child, die! */
406 if (kill (pid
, SIGKILL
) != 0)
408 printf ("kill (%d, SIGKILL): %m\n", pid
);
409 RETURN (EXIT_FAILURE
);
413 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
416 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOWAIT
);
420 printf ("waitid WNOWAIT returned bogus value %d\n", fail
);
421 RETURN (EXIT_FAILURE
);
423 printf ("waitid WNOWAIT on killed: %m\n");
424 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
426 if (info
.si_signo
!= SIGCHLD
)
428 printf ("waitid WNOWAIT on killed signal %d\n", info
.si_signo
);
429 RETURN (EXIT_FAILURE
);
431 if (info
.si_code
!= CLD_KILLED
)
433 printf ("waitid WNOWAIT on killed code %d\n", info
.si_code
);
434 RETURN (EXIT_FAILURE
);
436 if (info
.si_status
!= SIGKILL
)
438 printf ("waitid WNOWAIT on killed status %d\n", info
.si_status
);
439 RETURN (EXIT_FAILURE
);
441 if (info
.si_pid
!= pid
)
443 printf ("waitid WNOWAIT on killed pid %d != %d\n", info
.si_pid
, pid
);
444 RETURN (EXIT_FAILURE
);
448 /* Allow enough time to be sure the child died; we didn't synchronize. */
452 CHECK_SIGCHLD ("killed", CLD_KILLED
, SIGKILL
);
454 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
457 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOHANG
);
461 printf ("waitid WNOHANG returned bogus value %d\n", fail
);
462 RETURN (EXIT_FAILURE
);
464 printf ("waitid WNOHANG on killed: %m\n");
465 RETURN (EXIT_FAILURE
);
467 if (info
.si_signo
!= SIGCHLD
)
469 printf ("waitid WNOHANG on killed signal %d\n", info
.si_signo
);
470 RETURN (EXIT_FAILURE
);
472 if (info
.si_code
!= CLD_KILLED
)
474 printf ("waitid WNOHANG on killed code %d\n", info
.si_code
);
475 RETURN (EXIT_FAILURE
);
477 if (info
.si_status
!= SIGKILL
)
479 printf ("waitid WNOHANG on killed status %d\n", info
.si_status
);
480 RETURN (EXIT_FAILURE
);
482 if (info
.si_pid
!= pid
)
484 printf ("waitid WNOHANG on killed pid %d != %d\n", info
.si_pid
, pid
);
485 RETURN (EXIT_FAILURE
);
489 fail
= waitid (P_PID
, pid
, &info
, WEXITED
);
494 printf ("waitid WEXITED on killed: %m\n");
495 RETURN (EXIT_FAILURE
);
500 printf ("waitid WEXITED returned bogus value %d\n", fail
);
501 RETURN (EXIT_FAILURE
);
506 if (spurious_sigchld
)
507 status
= EXIT_FAILURE
;
508 signal (SIGCHLD
, SIG_IGN
);
509 kill (pid
, SIGKILL
); /* Make sure it's dead if we bailed early. */
513 #include "../test-skeleton.c"