diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | bits/waitstatus.h | 18 | ||||
-rw-r--r-- | posix/sys/wait.h | 7 | ||||
-rw-r--r-- | posix/tst-waitid.c | 71 | ||||
-rw-r--r-- | stdlib/stdlib.h | 3 | ||||
-rw-r--r-- | sysdeps/generic/bits/waitstatus.h | 18 |
6 files changed, 108 insertions, 18 deletions
@@ -1,5 +1,14 @@ 2004-09-27 Roland McGrath <roland@redhat.com> + * posix/tst-waitid.c (do_test): Add tests for waitpid with WCONTINUED. + + * posix/sys/wait.h [__WIFCONTINUED] (WIFCONTINUED): New macro. + * stdlib/stdlib.h [__WIFCONTINUED] (WIFCONTINUED): New macro. + * sysdeps/generic/bits/waitstatus.h (__W_CONTINUED): New macro. + [WCONTINUED] (__WIFCONTINUED): New macro. + (__WIFSIGNALED): Rewritten to exclude __W_CONTINUED value, and have no + branches. + * sysdeps/unix/sysv/linux/waitid.c (do_waitid): Add fifth argument to all three syscall uses, not just one! diff --git a/bits/waitstatus.h b/bits/waitstatus.h index 982c9dbb28..98da41858e 100644 --- a/bits/waitstatus.h +++ b/bits/waitstatus.h @@ -1,5 +1,5 @@ /* Definitions of status bits for `wait' et al. - Copyright (C) 1992, 1994, 1996, 1997, 2000 Free Software Foundation, Inc. + Copyright (C) 1992,1994,1996,1997,2000,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -38,23 +38,25 @@ #define __WIFEXITED(status) (__WTERMSIG(status) == 0) /* Nonzero if STATUS indicates termination by a signal. */ -#ifdef __GNUC__ -# define __WIFSIGNALED(status) \ - (__extension__ ({ int __status = (status); \ - !__WIFSTOPPED(__status) && !__WIFEXITED(__status); })) -#else /* Not GCC. */ -# define __WIFSIGNALED(status) (!__WIFSTOPPED(status) && !__WIFEXITED(status)) -#endif /* GCC. */ +#define __WIFSIGNALED(status) \ + (((signed char) ((((((status) + 1) & 0xffff) - 1) & 0x7f) + 1) >> 1) > 0) /* Nonzero if STATUS indicates the child is stopped. */ #define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +/* Nonzero if STATUS indicates the child continued after a stop. We only + define this if <bits/waitflags.h> provides the WCONTINUED flag bit. */ +#ifdef WCONTINUED +# define __WIFCONTINUED(status) ((status) == __W_CONTINUED) +#endif + /* Nonzero if STATUS indicates the child dumped core. */ #define __WCOREDUMP(status) ((status) & __WCOREFLAG) /* Macros for constructing status values. */ #define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) #define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) +#define __W_CONTINUED 0xffff #define __WCOREFLAG 0x80 diff --git a/posix/sys/wait.h b/posix/sys/wait.h index e758f9e3ff..372d46c79a 100644 --- a/posix/sys/wait.h +++ b/posix/sys/wait.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-1994,1996-2001,2003 Free Software Foundation, Inc. +/* Copyright (C) 1991-1994,1996-2001,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -30,7 +30,7 @@ __BEGIN_DECLS #include <signal.h> #include <sys/resource.h> -/* These macros could also be defined int <stdlib.h>. */ +/* These macros could also be defined in <stdlib.h>. */ #if !defined _STDLIB_H || !defined __USE_XOPEN /* This will define the `W*' macros for the flag bits to `waitpid', `wait3', and `wait4'. */ @@ -84,6 +84,9 @@ typedef union # define WIFEXITED(status) __WIFEXITED(__WAIT_INT(status)) # define WIFSIGNALED(status) __WIFSIGNALED(__WAIT_INT(status)) # define WIFSTOPPED(status) __WIFSTOPPED(__WAIT_INT(status)) +# ifdef __WIFCONTINUED +# define WIFCONTINUED(status) __WIFCONTINUED(__WAIT_INT(status)) +# endif #endif /* <stdlib.h> not included. */ #ifdef __USE_BSD diff --git a/posix/tst-waitid.c b/posix/tst-waitid.c index 3e81d7a0ac..642d529a9a 100644 --- a/posix/tst-waitid.c +++ b/posix/tst-waitid.c @@ -335,6 +335,77 @@ do_test (int argc, char *argv[]) info.si_signo); RETURN (EXIT_FAILURE); } + + /* Now stop him again and test waitpid with WCONTINUED. */ + expecting_sigchld = 1; + if (kill (pid, SIGSTOP) != 0) + { + error (0, errno, "kill (%d, SIGSTOP)", pid); + RETURN (EXIT_FAILURE); + } + pid_t wpid = waitpid (pid, &fail, WUNTRACED); + if (wpid < 0) + { + error (0, errno, "waitpid WUNTRACED on stopped"); + RETURN (EXIT_FAILURE); + } + else if (wpid != pid) + { + error (0, 0, + "waitpid WUNTRACED on stopped returned %d != %d (status %x)", + wpid, pid, fail); + RETURN (EXIT_FAILURE); + } + else if (!WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail) + || WIFCONTINUED (fail) || WSTOPSIG (fail) != SIGSTOP) + { + error (0, 0, "waitpid WUNTRACED on stopped: status %x", fail); + RETURN (EXIT_FAILURE); + } + CHECK_SIGCHLD ("stopped", CLD_STOPPED, SIGSTOP); + + expecting_sigchld = 1; + if (kill (pid, SIGCONT) != 0) + { + error (0, errno, "kill (%d, SIGCONT)", pid); + RETURN (EXIT_FAILURE); + } + + /* Wait for the child to have continued. */ + sleep (2); + + if (expecting_sigchld) + { + error (0, 0, "no SIGCHLD seen for SIGCONT (optional)"); + expecting_sigchld = 0; + } + else + CHECK_SIGCHLD ("continued", CLD_CONTINUED, SIGCONT); + + wpid = waitpid (pid, &fail, WCONTINUED); + if (wpid < 0) + { + if (errno == EINVAL) + error (0, 0, "waitpid does not support WCONTINUED"); + else + { + error (0, errno, "waitpid WCONTINUED on continued"); + RETURN (EXIT_FAILURE); + } + } + else if (wpid != pid) + { + error (0, 0, + "waitpid WCONTINUED on continued returned %d != %d (status %x)", + wpid, pid, fail); + RETURN (EXIT_FAILURE); + } + else if (WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail) + || !WIFCONTINUED (fail)) + { + error (0, 0, "waitpid WCONTINUED on continued: status %x", fail); + RETURN (EXIT_FAILURE); + } #endif expecting_sigchld = 1; diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h index dc0c712df7..e4f79369a6 100644 --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h @@ -88,6 +88,9 @@ typedef union # define WIFEXITED(status) __WIFEXITED(__WAIT_INT(status)) # define WIFSIGNALED(status) __WIFSIGNALED(__WAIT_INT(status)) # define WIFSTOPPED(status) __WIFSTOPPED(__WAIT_INT(status)) +# ifdef __WIFCONTINUED +# define WIFCONTINUED(status) __WIFCONTINUED(__WAIT_INT(status)) +# endif #endif /* X/Open and <sys/wait.h> not included. */ __BEGIN_NAMESPACE_STD diff --git a/sysdeps/generic/bits/waitstatus.h b/sysdeps/generic/bits/waitstatus.h index 982c9dbb28..98da41858e 100644 --- a/sysdeps/generic/bits/waitstatus.h +++ b/sysdeps/generic/bits/waitstatus.h @@ -1,5 +1,5 @@ /* Definitions of status bits for `wait' et al. - Copyright (C) 1992, 1994, 1996, 1997, 2000 Free Software Foundation, Inc. + Copyright (C) 1992,1994,1996,1997,2000,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -38,23 +38,25 @@ #define __WIFEXITED(status) (__WTERMSIG(status) == 0) /* Nonzero if STATUS indicates termination by a signal. */ -#ifdef __GNUC__ -# define __WIFSIGNALED(status) \ - (__extension__ ({ int __status = (status); \ - !__WIFSTOPPED(__status) && !__WIFEXITED(__status); })) -#else /* Not GCC. */ -# define __WIFSIGNALED(status) (!__WIFSTOPPED(status) && !__WIFEXITED(status)) -#endif /* GCC. */ +#define __WIFSIGNALED(status) \ + (((signed char) ((((((status) + 1) & 0xffff) - 1) & 0x7f) + 1) >> 1) > 0) /* Nonzero if STATUS indicates the child is stopped. */ #define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +/* Nonzero if STATUS indicates the child continued after a stop. We only + define this if <bits/waitflags.h> provides the WCONTINUED flag bit. */ +#ifdef WCONTINUED +# define __WIFCONTINUED(status) ((status) == __W_CONTINUED) +#endif + /* Nonzero if STATUS indicates the child dumped core. */ #define __WCOREDUMP(status) ((status) & __WCOREFLAG) /* Macros for constructing status values. */ #define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) #define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) +#define __W_CONTINUED 0xffff #define __WCOREFLAG 0x80 |