2 Copyright (C) 2004-2019 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 <https://www.gnu.org/licenses/>. */
29 /* Wait a second to be sure the parent set his variables before we
33 /* First thing, we stop ourselves. */
36 /* Hey, we got continued! */
44 # define WSTOPPED WUNTRACED
47 static sig_atomic_t expecting_sigchld
, spurious_sigchld
;
49 static siginfo_t sigchld_info
;
52 sigchld (int signo
, siginfo_t
*info
, void *ctx
)
56 printf ("SIGCHLD handler got signal %d instead!\n", signo
);
60 if (! expecting_sigchld
)
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
);
69 expecting_sigchld
= 0;
74 check_sigchld (const char *phase
, int *ok
, int code
, int status
, pid_t pid
)
76 if (expecting_sigchld
)
78 printf ("missing SIGCHLD on %s\n", phase
);
80 expecting_sigchld
= 0;
84 if (sigchld_info
.si_signo
!= SIGCHLD
)
86 printf ("SIGCHLD for %s signal %d\n", phase
, sigchld_info
.si_signo
);
89 if (sigchld_info
.si_code
!= code
)
91 printf ("SIGCHLD for %s code %d\n", phase
, sigchld_info
.si_code
);
94 if (sigchld_info
.si_status
!= status
)
96 printf ("SIGCHLD for %s status %d\n", phase
, sigchld_info
.si_status
);
99 if (sigchld_info
.si_pid
!= pid
)
101 printf ("SIGCHLD for %s pid %d\n", phase
, sigchld_info
.si_pid
);
105 # define CHECK_SIGCHLD(phase, code_check, status_check) \
106 check_sigchld ((phase), &status, (code_check), (status_check), pid)
108 # define CHECK_SIGCHLD(phase, code, status) ((void) 0)
112 do_test (int argc
, char *argv
[])
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)
120 printf ("setting SIGCHLD handler: %m\n");
125 expecting_sigchld
= 1;
130 printf ("fork: %m\n");
139 int status
= EXIT_SUCCESS
;
141 do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0)
143 /* Give the child a chance to stop. */
146 CHECK_SIGCHLD ("stopped (before waitid)", CLD_STOPPED
, SIGSTOP
);
148 /* Now try a wait that should not succeed. */
150 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
151 int fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WCONTINUED
|WNOHANG
);
155 printf ("waitid returned bogus value %d\n", fail
);
156 RETURN (EXIT_FAILURE
);
158 printf ("waitid WNOHANG on stopped: %m\n");
159 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
161 if (info
.si_signo
== 0)
163 if (info
.si_signo
== SIGCHLD
)
164 printf ("waitid WNOHANG on stopped status %d\n", info
.si_status
);
166 printf ("waitid WNOHANG on stopped signal %d\n", info
.si_signo
);
167 RETURN (EXIT_FAILURE
);
170 /* Next the wait that should succeed right away. */
171 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
174 fail
= waitid (P_PID
, pid
, &info
, WSTOPPED
|WNOHANG
);
178 printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail
);
179 RETURN (EXIT_FAILURE
);
181 printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n");
182 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
184 if (info
.si_signo
!= SIGCHLD
)
186 printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n",
188 RETURN (EXIT_FAILURE
);
190 if (info
.si_code
!= CLD_STOPPED
)
192 printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n",
194 RETURN (EXIT_FAILURE
);
196 if (info
.si_status
!= SIGSTOP
)
198 printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n",
200 RETURN (EXIT_FAILURE
);
202 if (info
.si_pid
!= pid
)
204 printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
206 RETURN (EXIT_FAILURE
);
210 expecting_sigchld
= WCONTINUED
!= 0;
212 if (kill (pid
, SIGCONT
) != 0)
214 printf ("kill (%d, SIGCONT): %m\n", pid
);
215 RETURN (EXIT_FAILURE
);
218 /* Wait for the child to have continued. */
222 if (expecting_sigchld
)
224 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
225 expecting_sigchld
= 0;
228 CHECK_SIGCHLD ("continued (before waitid)", CLD_CONTINUED
, SIGCONT
);
230 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
233 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
|WNOWAIT
);
237 printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail
);
238 RETURN (EXIT_FAILURE
);
240 printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n");
241 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
243 if (info
.si_signo
!= SIGCHLD
)
245 printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n",
247 RETURN (EXIT_FAILURE
);
249 if (info
.si_code
!= CLD_CONTINUED
)
251 printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n",
253 RETURN (EXIT_FAILURE
);
255 if (info
.si_status
!= SIGCONT
)
257 printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n",
259 RETURN (EXIT_FAILURE
);
261 if (info
.si_pid
!= pid
)
263 printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
265 RETURN (EXIT_FAILURE
);
269 /* That should leave the CLD_CONTINUED state waiting to be seen again. */
270 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
273 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
);
277 printf ("waitid WCONTINUED returned bogus value %d\n", fail
);
278 RETURN (EXIT_FAILURE
);
280 printf ("waitid WCONTINUED on continued: %m\n");
281 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
283 if (info
.si_signo
!= SIGCHLD
)
285 printf ("waitid WCONTINUED on continued signal %d\n", info
.si_signo
);
286 RETURN (EXIT_FAILURE
);
288 if (info
.si_code
!= CLD_CONTINUED
)
290 printf ("waitid WCONTINUED on continued code %d\n", info
.si_code
);
291 RETURN (EXIT_FAILURE
);
293 if (info
.si_status
!= SIGCONT
)
295 printf ("waitid WCONTINUED on continued status %d\n",
297 RETURN (EXIT_FAILURE
);
299 if (info
.si_pid
!= pid
)
301 printf ("waitid WCONTINUED on continued pid %d != %d\n",
303 RETURN (EXIT_FAILURE
);
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
);
313 printf ("waitid returned bogus value %d\n", fail
);
314 RETURN (EXIT_FAILURE
);
316 printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n");
317 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
319 if (info
.si_signo
== 0)
321 if (info
.si_signo
== SIGCHLD
)
322 printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n",
325 printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
327 RETURN (EXIT_FAILURE
);
330 /* Now stop him again and test waitpid with WCONTINUED. */
331 expecting_sigchld
= 1;
332 if (kill (pid
, SIGSTOP
) != 0)
334 printf ("kill (%d, SIGSTOP): %m\n", pid
);
335 RETURN (EXIT_FAILURE
);
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. */
344 pid_t wpid
= waitpid (pid
, &fail
, WUNTRACED
);
347 printf ("waitpid WUNTRACED on stopped: %m\n");
348 RETURN (EXIT_FAILURE
);
350 else if (wpid
!= pid
)
352 printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n",
354 RETURN (EXIT_FAILURE
);
356 else if (!WIFSTOPPED (fail
) || WIFSIGNALED (fail
) || WIFEXITED (fail
)
357 || WIFCONTINUED (fail
) || WSTOPSIG (fail
) != SIGSTOP
)
359 printf ("waitpid WUNTRACED on stopped: status %x\n", fail
);
360 RETURN (EXIT_FAILURE
);
362 CHECK_SIGCHLD ("stopped (after waitpid)", CLD_STOPPED
, SIGSTOP
);
364 expecting_sigchld
= 1;
365 if (kill (pid
, SIGCONT
) != 0)
367 printf ("kill (%d, SIGCONT): %m\n", pid
);
368 RETURN (EXIT_FAILURE
);
371 /* Wait for the child to have continued. */
374 if (expecting_sigchld
)
376 printf ("no SIGCHLD seen for SIGCONT (optional)\n");
377 expecting_sigchld
= 0;
380 CHECK_SIGCHLD ("continued (before waitpid)", CLD_CONTINUED
, SIGCONT
);
382 wpid
= waitpid (pid
, &fail
, WCONTINUED
);
386 printf ("waitpid does not support WCONTINUED\n");
389 printf ("waitpid WCONTINUED on continued: %m\n");
390 RETURN (EXIT_FAILURE
);
393 else if (wpid
!= pid
)
396 waitpid WCONTINUED on continued returned %d != %d (status %x)\n",
398 RETURN (EXIT_FAILURE
);
400 else if (WIFSTOPPED (fail
) || WIFSIGNALED (fail
) || WIFEXITED (fail
)
401 || !WIFCONTINUED (fail
))
403 printf ("waitpid WCONTINUED on continued: status %x\n", fail
);
404 RETURN (EXIT_FAILURE
);
408 expecting_sigchld
= 1;
410 /* Die, child, die! */
411 if (kill (pid
, SIGKILL
) != 0)
413 printf ("kill (%d, SIGKILL): %m\n", pid
);
414 RETURN (EXIT_FAILURE
);
418 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
421 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOWAIT
);
425 printf ("waitid WNOWAIT returned bogus value %d\n", fail
);
426 RETURN (EXIT_FAILURE
);
428 printf ("waitid WNOWAIT on killed: %m\n");
429 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
431 if (info
.si_signo
!= SIGCHLD
)
433 printf ("waitid WNOWAIT on killed signal %d\n", info
.si_signo
);
434 RETURN (EXIT_FAILURE
);
436 if (info
.si_code
!= CLD_KILLED
)
438 printf ("waitid WNOWAIT on killed code %d\n", info
.si_code
);
439 RETURN (EXIT_FAILURE
);
441 if (info
.si_status
!= SIGKILL
)
443 printf ("waitid WNOWAIT on killed status %d\n", info
.si_status
);
444 RETURN (EXIT_FAILURE
);
446 if (info
.si_pid
!= pid
)
448 printf ("waitid WNOWAIT on killed pid %d != %d\n", info
.si_pid
, pid
);
449 RETURN (EXIT_FAILURE
);
453 /* Allow enough time to be sure the child died; we didn't synchronize. */
457 CHECK_SIGCHLD ("killed", CLD_KILLED
, SIGKILL
);
459 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
462 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOHANG
);
466 printf ("waitid WNOHANG returned bogus value %d\n", fail
);
467 RETURN (EXIT_FAILURE
);
469 printf ("waitid WNOHANG on killed: %m\n");
470 RETURN (EXIT_FAILURE
);
472 if (info
.si_signo
!= SIGCHLD
)
474 printf ("waitid WNOHANG on killed signal %d\n", info
.si_signo
);
475 RETURN (EXIT_FAILURE
);
477 if (info
.si_code
!= CLD_KILLED
)
479 printf ("waitid WNOHANG on killed code %d\n", info
.si_code
);
480 RETURN (EXIT_FAILURE
);
482 if (info
.si_status
!= SIGKILL
)
484 printf ("waitid WNOHANG on killed status %d\n", info
.si_status
);
485 RETURN (EXIT_FAILURE
);
487 if (info
.si_pid
!= pid
)
489 printf ("waitid WNOHANG on killed pid %d != %d\n", info
.si_pid
, pid
);
490 RETURN (EXIT_FAILURE
);
494 fail
= waitid (P_PID
, pid
, &info
, WEXITED
);
499 printf ("waitid WEXITED on killed: %m\n");
500 RETURN (EXIT_FAILURE
);
505 printf ("waitid WEXITED returned bogus value %d\n", fail
);
506 RETURN (EXIT_FAILURE
);
511 if (spurious_sigchld
)
512 status
= EXIT_FAILURE
;
513 signal (SIGCHLD
, SIG_IGN
);
514 kill (pid
, SIGKILL
); /* Make sure it's dead if we bailed early. */
518 #include "../test-skeleton.c"