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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
32 /* Wait a second to be sure the parent set his variables before we
36 /* First thing, we stop ourselves. */
39 /* Hey, we got continued! */
47 # define WSTOPPED WUNTRACED
50 static sig_atomic_t expecting_sigchld
, spurious_sigchld
;
52 static siginfo_t sigchld_info
;
55 sigchld (int signo
, siginfo_t
*info
, void *ctx
)
59 error (0, 0, "SIGCHLD handler got signal %d instead!", signo
);
63 if (! expecting_sigchld
)
67 "spurious SIGCHLD: signo %d code %d status %d pid %d\n",
68 info
->si_signo
, info
->si_code
, info
->si_status
, info
->si_pid
);
73 expecting_sigchld
= 0;
78 check_sigchld (const char *phase
, int *ok
, int code
, int status
, pid_t pid
)
80 if (expecting_sigchld
)
82 error (0, 0, "missing SIGCHLD on %s", phase
);
84 expecting_sigchld
= 0;
88 if (sigchld_info
.si_signo
!= SIGCHLD
)
90 error (0, 0, "SIGCHLD for %s signal %d", phase
, sigchld_info
.si_signo
);
93 if (sigchld_info
.si_code
!= code
)
95 error (0, 0, "SIGCHLD for %s code %d", phase
, sigchld_info
.si_code
);
98 if (sigchld_info
.si_status
!= status
)
100 error (0, 0, "SIGCHLD for %s status %d", phase
, sigchld_info
.si_status
);
103 if (sigchld_info
.si_pid
!= pid
)
105 error (0, 0, "SIGCHLD for %s pid %d", phase
, sigchld_info
.si_pid
);
109 # define CHECK_SIGCHLD(phase, code_check, status_check) \
110 check_sigchld ((phase), &status, (code_check), (status_check), pid)
112 # define CHECK_SIGCHLD(phase, code, status) ((void) 0)
116 do_test (int argc
, char *argv
[])
120 sa
.sa_flags
= SA_SIGINFO
|SA_RESTART
;
121 sa
.sa_sigaction
= &sigchld
;
122 if (sigemptyset (&sa
.sa_mask
) < 0 || sigaction (SIGCHLD
, &sa
, NULL
) < 0)
124 error (0, errno
, "setting SIGCHLD handler");
129 expecting_sigchld
= 1;
134 error (0, errno
, "fork");
143 int status
= EXIT_SUCCESS
;
145 do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0)
147 /* Give the child a chance to stop. */
150 CHECK_SIGCHLD ("stopped", CLD_STOPPED
, SIGSTOP
);
152 /* Now try a wait that should not succeed. */
154 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
155 int fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WCONTINUED
|WNOHANG
);
159 error (0, 0, "waitid returned bogus value %d\n", fail
);
160 RETURN (EXIT_FAILURE
);
162 error (0, errno
, "waitid WNOHANG on stopped");
163 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
165 if (info
.si_signo
== 0)
167 if (info
.si_signo
== SIGCHLD
)
168 error (0, 0, "waitid WNOHANG on stopped status %d\n", info
.si_status
);
170 error (0, 0, "waitid WNOHANG on stopped signal %d\n", info
.si_signo
);
171 RETURN (EXIT_FAILURE
);
174 /* Next the wait that should succeed right away. */
175 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
178 fail
= waitid (P_PID
, pid
, &info
, WSTOPPED
|WNOHANG
);
182 error (0, 0, "waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail
);
183 RETURN (EXIT_FAILURE
);
185 error (0, errno
, "waitid WSTOPPED|WNOHANG on stopped");
186 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
188 if (info
.si_signo
!= SIGCHLD
)
190 error (0, 0, "waitid WSTOPPED|WNOHANG on stopped signal %d\n",
192 RETURN (EXIT_FAILURE
);
194 if (info
.si_code
!= CLD_STOPPED
)
196 error (0, 0, "waitid WSTOPPED|WNOHANG on stopped code %d\n",
198 RETURN (EXIT_FAILURE
);
200 if (info
.si_status
!= SIGSTOP
)
202 error (0, 0, "waitid WSTOPPED|WNOHANG on stopped status %d\n",
204 RETURN (EXIT_FAILURE
);
206 if (info
.si_pid
!= pid
)
208 error (0, 0, "waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
210 RETURN (EXIT_FAILURE
);
214 expecting_sigchld
= WCONTINUED
!= 0;
216 if (kill (pid
, SIGCONT
) != 0)
218 error (0, errno
, "kill (%d, SIGCONT)", pid
);
219 RETURN (EXIT_FAILURE
);
222 /* Wait for the child to have continued. */
226 if (expecting_sigchld
)
228 error (0, 0, "no SIGCHLD seen for SIGCONT (optional)");
229 expecting_sigchld
= 0;
232 CHECK_SIGCHLD ("continued", CLD_CONTINUED
, SIGCONT
);
234 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
237 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
|WNOWAIT
);
242 "waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail
);
243 RETURN (EXIT_FAILURE
);
245 error (0, errno
, "waitid WCONTINUED|WNOWAIT on continued");
246 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
248 if (info
.si_signo
!= SIGCHLD
)
250 error (0, 0, "waitid WCONTINUED|WNOWAIT on continued signal %d\n",
252 RETURN (EXIT_FAILURE
);
254 if (info
.si_code
!= CLD_CONTINUED
)
256 error (0, 0, "waitid WCONTINUED|WNOWAIT on continued code %d\n",
258 RETURN (EXIT_FAILURE
);
260 if (info
.si_status
!= SIGCONT
)
262 error (0, 0, "waitid WCONTINUED|WNOWAIT on continued status %d\n",
264 RETURN (EXIT_FAILURE
);
266 if (info
.si_pid
!= pid
)
268 error (0, 0, "waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
270 RETURN (EXIT_FAILURE
);
274 /* That should leave the CLD_CONTINUED state waiting to be seen again. */
275 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
278 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
);
282 error (0, 0, "waitid WCONTINUED returned bogus value %d\n", fail
);
283 RETURN (EXIT_FAILURE
);
285 error (0, errno
, "waitid WCONTINUED on continued");
286 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
288 if (info
.si_signo
!= SIGCHLD
)
290 error (0, 0, "waitid WCONTINUED on continued signal %d\n",
292 RETURN (EXIT_FAILURE
);
294 if (info
.si_code
!= CLD_CONTINUED
)
296 error (0, 0, "waitid WCONTINUED on continued code %d\n",
298 RETURN (EXIT_FAILURE
);
300 if (info
.si_status
!= SIGCONT
)
302 error (0, 0, "waitid WCONTINUED on continued status %d\n",
304 RETURN (EXIT_FAILURE
);
306 if (info
.si_pid
!= pid
)
308 error (0, 0, "waitid WCONTINUED on continued pid %d != %d\n",
310 RETURN (EXIT_FAILURE
);
314 /* Now try a wait that should not succeed. */
315 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
316 fail
= waitid (P_PID
, pid
, &info
, WCONTINUED
|WNOHANG
);
320 error (0, 0, "waitid returned bogus value %d\n", fail
);
321 RETURN (EXIT_FAILURE
);
323 error (0, errno
, "waitid WCONTINUED|WNOHANG on waited continued");
324 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
326 if (info
.si_signo
== 0)
328 if (info
.si_signo
== SIGCHLD
)
330 "waitid WCONTINUED|WNOHANG on waited continued status %d\n",
334 "waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
336 RETURN (EXIT_FAILURE
);
340 expecting_sigchld
= 1;
342 /* Die, child, die! */
343 if (kill (pid
, SIGKILL
) != 0)
345 error (0, errno
, "kill (%d, SIGKILL)", pid
);
346 RETURN (EXIT_FAILURE
);
350 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
353 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOWAIT
);
357 error (0, 0, "waitid WNOWAIT returned bogus value %d\n", fail
);
358 RETURN (EXIT_FAILURE
);
360 error (0, errno
, "waitid WNOWAIT on killed");
361 RETURN (errno
== ENOTSUP
? EXIT_SUCCESS
: EXIT_FAILURE
);
363 if (info
.si_signo
!= SIGCHLD
)
365 error (0, 0, "waitid WNOWAIT on killed signal %d\n",
367 RETURN (EXIT_FAILURE
);
369 if (info
.si_code
!= CLD_KILLED
)
371 error (0, 0, "waitid WNOWAIT on killed code %d\n",
373 RETURN (EXIT_FAILURE
);
375 if (info
.si_status
!= SIGKILL
)
377 error (0, 0, "waitid WNOWAIT on killed status %d\n",
379 RETURN (EXIT_FAILURE
);
381 if (info
.si_pid
!= pid
)
383 error (0, 0, "waitid WNOWAIT on killed pid %d != %d\n",
385 RETURN (EXIT_FAILURE
);
389 /* Allow enough time to be sure the child died; we didn't synchronize. */
393 CHECK_SIGCHLD ("killed", CLD_KILLED
, SIGKILL
);
395 info
.si_signo
= 0; /* A successful call sets it to SIGCHLD. */
398 fail
= waitid (P_PID
, pid
, &info
, WEXITED
|WNOHANG
);
402 error (0, 0, "waitid WNOHANG returned bogus value %d\n", fail
);
403 RETURN (EXIT_FAILURE
);
405 error (0, errno
, "waitid WNOHANG on killed");
406 RETURN (EXIT_FAILURE
);
408 if (info
.si_signo
!= SIGCHLD
)
410 error (0, 0, "waitid WNOHANG on killed signal %d\n",
412 RETURN (EXIT_FAILURE
);
414 if (info
.si_code
!= CLD_KILLED
)
416 error (0, 0, "waitid WNOHANG on killed code %d\n",
418 RETURN (EXIT_FAILURE
);
420 if (info
.si_status
!= SIGKILL
)
422 error (0, 0, "waitid WNOHANG on killed status %d\n",
424 RETURN (EXIT_FAILURE
);
426 if (info
.si_pid
!= pid
)
428 error (0, 0, "waitid WNOHANG on killed pid %d != %d\n",
430 RETURN (EXIT_FAILURE
);
434 fail
= waitid (P_PID
, pid
, &info
, WEXITED
);
439 error (0, errno
, "waitid WEXITED on killed");
440 RETURN (EXIT_FAILURE
);
445 error (0, 0, "waitid WEXITED returned bogus value %d\n", fail
);
446 RETURN (EXIT_FAILURE
);
451 if (spurious_sigchld
)
452 status
= EXIT_FAILURE
;
453 signal (SIGCHLD
, SIG_IGN
);
454 kill (pid
, SIGKILL
); /* Make sure it's dead if we bailed early. */
458 #include "../test-skeleton.c"