From b49ab5f4503f36dcbf43f821f817da66b2931fe6 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 14 Apr 2016 08:54:57 +0200 Subject: [PATCH] Remove union wait [BZ #19613] The overloading approach in the W* macros was incompatible with integer expressions of a type different from int. Applications using union wait and these macros will have to migrate to the POSIX-specified int status type. --- ChangeLog | 31 +++++++++++++++++ NEWS | 4 +++ bits/waitstatus.h | 46 ------------------------- include/sys/wait.h | 6 ++-- manual/process.texi | 48 ++++---------------------- posix/sys/wait.h | 61 ++++++---------------------------- posix/wait.c | 2 +- posix/wait3.c | 2 +- posix/wait4.c | 3 +- stdlib/stdlib.h | 53 ++++------------------------- sysdeps/mach/hurd/wait4.c | 3 +- sysdeps/posix/wait.c | 2 +- sysdeps/posix/wait3.c | 2 +- sysdeps/unix/bsd/wait.c | 2 +- sysdeps/unix/bsd/wait3.c | 2 +- sysdeps/unix/bsd/waitpid.c | 2 +- sysdeps/unix/sysv/linux/wait.c | 2 +- 17 files changed, 72 insertions(+), 199 deletions(-) diff --git a/ChangeLog b/ChangeLog index f880712ef0..304171b55c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2016-04-14 Florian Weimer + + [BZ #19613] + Remove union wait. + * bits/waitstatus.h (union wait, w_termsig, w_coredump, w_retcode) + (w_stopsig, w_stopval): Remove. + * include/sys/wait.h (__wait, __wait3, __wait4): Use int * for the + stat_loc argument. + * posix/sys/wait.h (__WAIT_INT, __WAIT_STATUS) + (__WAIT_STATUS_DEFN): Remove. + (WEXITSTATUS, WTERMSIG, WSTOPSIG, WIFEXITED, WIFSIGNALED) + (WIFSTOPPED, WIFCONTINUED, WCOREDUMP): Remove __WAIT_INT. + (wait, wait3, wait4): Use int * for the stat_loc argument. + * posix/wait.c (__wait): Likewise. + * posix/wait3.c (__wait3): Likewise. + * posix/wait4.c (__wait4): Likewise. + * stdlib/stdlib.h (__WAIT_INT, __WAIT_STATUS) + (__WAIT_STATUS_DEFN): Remove. + (WEXITSTATUS, WTERMSIG, WSTOPSIG, WIFEXITED, WIFSIGNALED) + (WIFSTOPPED, WIFCONTINUED): Remove __WAIT_INT. + * sysdeps/mach/hurd/wait4.c (__wait4): Use int * for the stat_loc + argument. + * sysdeps/posix/wait.c (__libc_wait): Likewise. + * sysdeps/posix/wait3.c (__wait3): Likewise. + * sysdeps/unix/bsd/wait.c (__libc_wait): Likewise. + * sysdeps/unix/bsd/wait3.c (__wait3): Likewise. + * sysdeps/unix/bsd/waitpid.c (__waitpid): Remove cast. + * sysdeps/unix/sysv/linux/wait.c (__libc_wait): Use int * for the + stat_loc argument. + * manual/process.texi (BSD Wait Functions): Remove union wait. + 2016-04-13 Andreas Schwab * elf/Makefile (extra-test-objs): Add tst-tlsalign-vars.o. diff --git a/NEWS b/NEWS index a06a42f62a..54ffb02c4d 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ Version 2.24 * The readdir_r and readdir64_r functions have been deprecated. It is recommended to use readdir and readdir64 instead. +* The type “union wait” has been removed. It was deprecated in the early + 1990s and never part of POSIX. Application code should use the int type + instead of “union wait”. + Security related changes: [Add security related changes here] diff --git a/bits/waitstatus.h b/bits/waitstatus.h index 38c33bc2dc..069ce4b62b 100644 --- a/bits/waitstatus.h +++ b/bits/waitstatus.h @@ -57,49 +57,3 @@ #define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) #define __W_CONTINUED 0xffff #define __WCOREFLAG 0x80 - - -#ifdef __USE_MISC - -# include - -union wait - { - int w_status; - struct - { -# if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int __w_termsig:7; /* Terminating signal. */ - unsigned int __w_coredump:1; /* Set if dumped core. */ - unsigned int __w_retcode:8; /* Return code if exited normally. */ - unsigned int:16; -# endif /* Little endian. */ -# if __BYTE_ORDER == __BIG_ENDIAN - unsigned int:16; - unsigned int __w_retcode:8; - unsigned int __w_coredump:1; - unsigned int __w_termsig:7; -# endif /* Big endian. */ - } __wait_terminated; - struct - { -# if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int __w_stopval:8; /* W_STOPPED if stopped. */ - unsigned int __w_stopsig:8; /* Stopping signal. */ - unsigned int:16; -# endif /* Little endian. */ -# if __BYTE_ORDER == __BIG_ENDIAN - unsigned int:16; - unsigned int __w_stopsig:8; /* Stopping signal. */ - unsigned int __w_stopval:8; /* W_STOPPED if stopped. */ -# endif /* Big endian. */ - } __wait_stopped; - }; - -# define w_termsig __wait_terminated.__w_termsig -# define w_coredump __wait_terminated.__w_coredump -# define w_retcode __wait_terminated.__w_retcode -# define w_stopsig __wait_stopped.__w_stopsig -# define w_stopval __wait_stopped.__w_stopval - -#endif /* Use misc. */ diff --git a/include/sys/wait.h b/include/sys/wait.h index 9a38e61be7..5ac9cd6ca6 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -9,10 +9,10 @@ libc_hidden_proto (__waitpid) extern int __waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options); extern __pid_t __libc_wait (int *__stat_loc); -extern __pid_t __wait (__WAIT_STATUS __stat_loc); -extern __pid_t __wait3 (__WAIT_STATUS __stat_loc, +extern __pid_t __wait (int *__stat_loc); +extern __pid_t __wait3 (int *__stat_loc, int __options, struct rusage * __usage); -extern __pid_t __wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, +extern __pid_t __wait4 (__pid_t __pid, int *__stat_loc, int __options, struct rusage *__usage) attribute_hidden; #endif diff --git a/manual/process.texi b/manual/process.texi index aa59040cb4..25bdb8ebb8 100644 --- a/manual/process.texi +++ b/manual/process.texi @@ -763,53 +763,17 @@ signal number of the signal that caused the child process to stop. @node BSD Wait Functions -@section BSD Process Wait Functions +@section BSD Process Wait Function -@Theglibc{} also provides these related facilities for compatibility -with BSD Unix. BSD uses the @code{union wait} data type to represent -status values rather than an @code{int}. The two representations are -actually interchangeable; they describe the same bit patterns. @Theglibc{} -defines macros such as @code{WEXITSTATUS} so that they will -work on either kind of object, and the @code{wait} function is defined -to accept either type of pointer as its @var{status-ptr} argument. - -These functions are declared in @file{sys/wait.h}. +@Theglibc{} also provides the @code{wait3} function for compatibility +with BSD. This function is declared in @file{sys/wait.h}. It is the +predecessor to @code{wait4}, which is more flexible. @code{wait3} is +now obsolete. @pindex sys/wait.h @comment sys/wait.h @comment BSD -@deftp {Data Type} {union wait} -This data type represents program termination status values. It has -the following members: - -@table @code -@item int w_termsig -The value of this member is the same as that of the -@code{WTERMSIG} macro. - -@item int w_coredump -The value of this member is the same as that of the -@code{WCOREDUMP} macro. - -@item int w_retcode -The value of this member is the same as that of the -@code{WEXITSTATUS} macro. - -@item int w_stopsig -The value of this member is the same as that of the -@code{WSTOPSIG} macro. -@end table - -Instead of accessing these members directly, you should use the -equivalent macros. -@end deftp - -The @code{wait3} function is the predecessor to @code{wait4}, which is -more flexible. @code{wait3} is now obsolete. - -@comment sys/wait.h -@comment BSD -@deftypefun pid_t wait3 (union wait *@var{status-ptr}, int @var{options}, struct rusage *@var{usage}) +@deftypefun pid_t wait3 (int *@var{status-ptr}, int @var{options}, struct rusage *@var{usage}) @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} If @var{usage} is a null pointer, @code{wait3} is equivalent to @code{waitpid (-1, @var{status-ptr}, @var{options})}. diff --git a/posix/sys/wait.h b/posix/sys/wait.h index a673b414b5..acda43a337 100644 --- a/posix/sys/wait.h +++ b/posix/sys/wait.h @@ -34,62 +34,23 @@ __BEGIN_DECLS bits to `waitpid', `wait3', and `wait4'. */ # include -# ifdef __USE_MISC - -/* Lots of hair to allow traditional BSD use of `union wait' - as well as POSIX.1 use of `int' for the status word. */ - -# if defined __GNUC__ && !defined __cplusplus -# define __WAIT_INT(status) \ - (__extension__ (((union { __typeof(status) __in; int __i; }) \ - { .__in = (status) }).__i)) -# else -# define __WAIT_INT(status) (*(const int *) &(status)) -# endif - -/* This is the type of the argument to `wait'. The funky union - causes redeclarations with either `int *' or `union wait *' to be - allowed without complaint. __WAIT_STATUS_DEFN is the type used in - the actual function definitions. */ - -# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus -# define __WAIT_STATUS void * -# define __WAIT_STATUS_DEFN void * -# else -/* This works in GCC 2.6.1 and later. */ -typedef union - { - union wait *__uptr; - int *__iptr; - } __WAIT_STATUS __attribute__ ((__transparent_union__)); -# define __WAIT_STATUS_DEFN int * -# endif - -# else /* Don't use misc. */ - -# define __WAIT_INT(status) (status) -# define __WAIT_STATUS int * -# define __WAIT_STATUS_DEFN int * - -# endif /* Use misc. */ - /* This will define all the `__W*' macros. */ # include -# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status)) -# define WTERMSIG(status) __WTERMSIG (__WAIT_INT (status)) -# define WSTOPSIG(status) __WSTOPSIG (__WAIT_INT (status)) -# define WIFEXITED(status) __WIFEXITED (__WAIT_INT (status)) -# define WIFSIGNALED(status) __WIFSIGNALED (__WAIT_INT (status)) -# define WIFSTOPPED(status) __WIFSTOPPED (__WAIT_INT (status)) +# define WEXITSTATUS(status) __WEXITSTATUS (status) +# define WTERMSIG(status) __WTERMSIG (status) +# define WSTOPSIG(status) __WSTOPSIG (status) +# define WIFEXITED(status) __WIFEXITED (status) +# define WIFSIGNALED(status) __WIFSIGNALED (status) +# define WIFSTOPPED(status) __WIFSTOPPED (status) # ifdef __WIFCONTINUED -# define WIFCONTINUED(status) __WIFCONTINUED (__WAIT_INT (status)) +# define WIFCONTINUED(status) __WIFCONTINUED (status) # endif #endif /* not included. */ #ifdef __USE_MISC # define WCOREFLAG __WCOREFLAG -# define WCOREDUMP(status) __WCOREDUMP (__WAIT_INT (status)) +# define WCOREDUMP(status) __WCOREDUMP (status) # define W_EXITCODE(ret, sig) __W_EXITCODE (ret, sig) # define W_STOPCODE(sig) __W_STOPCODE (sig) #endif @@ -110,7 +71,7 @@ typedef enum This function is a cancellation point and therefore not marked with __THROW. */ -extern __pid_t wait (__WAIT_STATUS __stat_loc); +extern __pid_t wait (int *__stat_loc); #ifdef __USE_MISC /* Special values for the PID argument to `waitpid' and `wait4'. */ @@ -170,13 +131,13 @@ struct rusage; nil, store information about the child's resource usage there. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ -extern __pid_t wait3 (__WAIT_STATUS __stat_loc, int __options, +extern __pid_t wait3 (int *__stat_loc, int __options, struct rusage * __usage) __THROWNL; #endif #ifdef __USE_MISC /* PID is like waitpid. Other args are like wait3. */ -extern __pid_t wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, int __options, +extern __pid_t wait4 (__pid_t __pid, int *__stat_loc, int __options, struct rusage *__usage) __THROWNL; #endif /* Use misc. */ diff --git a/posix/wait.c b/posix/wait.c index 3abf30e675..c49375b022 100644 --- a/posix/wait.c +++ b/posix/wait.c @@ -21,7 +21,7 @@ /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ __pid_t -__wait (__WAIT_STATUS_DEFN stat_loc) +__wait (int *stat_loc) { __set_errno (ENOSYS); return -1; diff --git a/posix/wait3.c b/posix/wait3.c index 356839aef8..e8c2930066 100644 --- a/posix/wait3.c +++ b/posix/wait3.c @@ -25,7 +25,7 @@ there. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ pid_t -__wait3 (__WAIT_STATUS_DEFN stat_loc, int options, struct rusage *usage) +__wait3 (int *stat_loc, int options, struct rusage *usage) { if ((options & ~(WNOHANG|WUNTRACED)) != 0) { diff --git a/posix/wait4.c b/posix/wait4.c index e5b03766f6..4137617dc6 100644 --- a/posix/wait4.c +++ b/posix/wait4.c @@ -20,8 +20,7 @@ #include pid_t -__wait4 (__pid_t pid, __WAIT_STATUS stat_loc, int options, - struct rusage *usage) +__wait4 (__pid_t pid, int *stat_loc, int options, struct rusage *usage) { __set_errno (ENOSYS); return (pid_t) -1; diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h index cc77708b23..d0c78facdd 100644 --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h @@ -41,54 +41,15 @@ __BEGIN_DECLS # include # include -# ifdef __USE_MISC - -/* Lots of hair to allow traditional BSD use of `union wait' - as well as POSIX.1 use of `int' for the status word. */ - -# if defined __GNUC__ && !defined __cplusplus -# define __WAIT_INT(status) \ - (__extension__ (((union { __typeof(status) __in; int __i; }) \ - { .__in = (status) }).__i)) -# else -# define __WAIT_INT(status) (*(int *) &(status)) -# endif - -/* This is the type of the argument to `wait'. The funky union - causes redeclarations with either `int *' or `union wait *' to be - allowed without complaint. __WAIT_STATUS_DEFN is the type used in - the actual function definitions. */ - -# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus -# define __WAIT_STATUS void * -# define __WAIT_STATUS_DEFN void * -# else -/* This works in GCC 2.6.1 and later. */ -typedef union - { - union wait *__uptr; - int *__iptr; - } __WAIT_STATUS __attribute__ ((__transparent_union__)); -# define __WAIT_STATUS_DEFN int * -# endif - -# else /* Don't use misc. */ - -# define __WAIT_INT(status) (status) -# define __WAIT_STATUS int * -# define __WAIT_STATUS_DEFN int * - -# endif /* Use misc. */ - /* Define the macros also would define this way. */ -# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status)) -# define WTERMSIG(status) __WTERMSIG (__WAIT_INT (status)) -# define WSTOPSIG(status) __WSTOPSIG (__WAIT_INT (status)) -# define WIFEXITED(status) __WIFEXITED (__WAIT_INT (status)) -# define WIFSIGNALED(status) __WIFSIGNALED (__WAIT_INT (status)) -# define WIFSTOPPED(status) __WIFSTOPPED (__WAIT_INT (status)) +# define WEXITSTATUS(status) __WEXITSTATUS (status) +# define WTERMSIG(status) __WTERMSIG (status) +# define WSTOPSIG(status) __WSTOPSIG (status) +# define WIFEXITED(status) __WIFEXITED (status) +# define WIFSIGNALED(status) __WIFSIGNALED (status) +# define WIFSTOPPED(status) __WIFSTOPPED (status) # ifdef __WIFCONTINUED -# define WIFCONTINUED(status) __WIFCONTINUED (__WAIT_INT (status)) +# define WIFCONTINUED(status) __WIFCONTINUED (status) # endif #endif /* X/Open or XPG7 and not included. */ diff --git a/sysdeps/mach/hurd/wait4.c b/sysdeps/mach/hurd/wait4.c index 3bc9fa83fb..f392a984db 100644 --- a/sysdeps/mach/hurd/wait4.c +++ b/sysdeps/mach/hurd/wait4.c @@ -22,8 +22,7 @@ #include pid_t -__wait4 (pid_t pid, __WAIT_STATUS_DEFN stat_loc, int options, - struct rusage *usage) +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) { pid_t dead; error_t err; diff --git a/sysdeps/posix/wait.c b/sysdeps/posix/wait.c index 7f1d71a45f..210ece8a07 100644 --- a/sysdeps/posix/wait.c +++ b/sysdeps/posix/wait.c @@ -21,7 +21,7 @@ /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ __pid_t -__libc_wait (__WAIT_STATUS_DEFN stat_loc) +__libc_wait (int *stat_loc) { return __waitpid (WAIT_ANY, (int *) stat_loc, 0); } diff --git a/sysdeps/posix/wait3.c b/sysdeps/posix/wait3.c index 2e76892bff..cf43d973a7 100644 --- a/sysdeps/posix/wait3.c +++ b/sysdeps/posix/wait3.c @@ -26,7 +26,7 @@ there. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ pid_t -__wait3 (__WAIT_STATUS stat_loc, int options, struct rusage *usage) +__wait3 (int *stat_loc, int options, struct rusage *usage) { if (usage != NULL) { diff --git a/sysdeps/unix/bsd/wait.c b/sysdeps/unix/bsd/wait.c index 31de60e764..a9e29f21f7 100644 --- a/sysdeps/unix/bsd/wait.c +++ b/sysdeps/unix/bsd/wait.c @@ -23,7 +23,7 @@ /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ __pid_t -__libc_wait (__WAIT_STATUS_DEFN stat_loc) +__libc_wait (int *stat_loc) { return __wait4 (WAIT_ANY, stat_loc, 0, (struct rusage *) NULL); } diff --git a/sysdeps/unix/bsd/wait3.c b/sysdeps/unix/bsd/wait3.c index 3f95ac7881..ee33a657e9 100644 --- a/sysdeps/unix/bsd/wait3.c +++ b/sysdeps/unix/bsd/wait3.c @@ -25,7 +25,7 @@ there. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ pid_t -__wait3 (__WAIT_STATUS stat_loc, int options, struct rusage *usage) +__wait3 (int *stat_loc, int options, struct rusage *usage) { return __wait4 (WAIT_ANY, stat_loc, options, usage); } diff --git a/sysdeps/unix/bsd/waitpid.c b/sysdeps/unix/bsd/waitpid.c index 083c686ad0..cfe56141a3 100644 --- a/sysdeps/unix/bsd/waitpid.c +++ b/sysdeps/unix/bsd/waitpid.c @@ -35,7 +35,7 @@ pid_t __waitpid (pid_t pid, int *stat_loc, int options) { - return __wait4 (pid, (union wait *) stat_loc, options, NULL); + return __wait4 (pid, stat_loc, options, NULL); } libc_hidden_def (__waitpid) diff --git a/sysdeps/unix/sysv/linux/wait.c b/sysdeps/unix/sysv/linux/wait.c index 71f9044b60..9b7c9c9a94 100644 --- a/sysdeps/unix/sysv/linux/wait.c +++ b/sysdeps/unix/sysv/linux/wait.c @@ -24,7 +24,7 @@ /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ pid_t -__libc_wait (__WAIT_STATUS_DEFN stat_loc) +__libc_wait (int *stat_loc) { pid_t result = SYSCALL_CANCEL (wait4, WAIT_ANY, stat_loc, 0, (struct rusage *) NULL);