* lib/stdlib.in.h (includes): Guarantee WEXITSTATUS. * modules/stdlib (Depends-on): Add sys_wait. * tests/test-sys_wait.c (main): Enhance test. * tests/test-stdlib.c (main): Likewise. * doc/posix-headers/stdlib.texi (stdlib.h): Document the bug.
Signed-off-by: Eric Blake <ebl...@redhat.com> --- While debating about whether to fix WEXITSTATUS(constant) for MacOS, I disovered this POSIX-compliance bug in MirBSD. Basically, POSIX guarantees that the system() return value can be parsed without having to manually drag in <sys/wait.h>. ChangeLog | 7 +++++++ doc/posix-headers/stdlib.texi | 4 ++++ lib/stdlib.in.h | 5 +++++ modules/stdlib | 1 + tests/test-stdlib.c | 32 ++++++++++++++++++++++++++------ tests/test-sys_wait.c | 23 ++++++++++++++++++++++- 6 files changed, 65 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffbb1c0..bacfce3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2010-09-15 Eric Blake <ebl...@redhat.com> + stdlib: work around MirBSD WEXITSTATUS bug + * lib/stdlib.in.h (includes): Guarantee WEXITSTATUS. + * modules/stdlib (Depends-on): Add sys_wait. + * tests/test-sys_wait.c (main): Enhance test. + * tests/test-stdlib.c (main): Likewise. + * doc/posix-headers/stdlib.texi (stdlib.h): Document the bug. + docs: mention MacOS issue with WEXITSTATUS(constant) * doc/posix-headers/sys_wait.texi (sys/wait.h): Document the issue. diff --git a/doc/posix-headers/stdlib.texi b/doc/posix-headers/stdlib.texi index e1d6aba..f400f62 100644 --- a/doc/posix-headers/stdlib.texi +++ b/doc/posix-headers/stdlib.texi @@ -17,6 +17,10 @@ stdlib.h Some platforms provide a @code{NULL} macro that cannot be used in arbitrary expressions: NetBSD 5.0 + +...@item +Some platforms fail to provide @code{WEXITSTATUS} and friends: +MirBSD 10. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index d4ac469..0c1c165 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -38,6 +38,11 @@ /* NetBSD 5.0 mis-defines NULL. */ #include <stddef.h> +/* MirBSD 10 fails to define WEXITSTATUS. */ +#ifndef WEXITSTATUS +# include <sys/wait.h> +#endif + /* Solaris declares getloadavg() in <sys/loadavg.h>. */ #if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@ # include <sys/loadavg.h> diff --git a/modules/stdlib b/modules/stdlib index 489f70a..f822aa3 100644 --- a/modules/stdlib +++ b/modules/stdlib @@ -11,6 +11,7 @@ c++defs include_next stddef stdint +sys_wait unistd warn-on-use diff --git a/tests/test-stdlib.c b/tests/test-stdlib.c index 4bd8715..8066b05 100644 --- a/tests/test-stdlib.c +++ b/tests/test-stdlib.c @@ -22,7 +22,17 @@ #include "verify.h" -int exitcode; +/* Check that EXIT_SUCCESS is 0, per POSIX. */ +static int exitcode = EXIT_SUCCESS; +#if EXIT_SUCCESS +"oops" +#endif + +/* Check for GNU value (not guaranteed by POSIX, but is guaranteed by + gnulib). */ +#if EXIT_FAILURE != 1 +"oops" +#endif /* Check that NULL can be passed through varargs as a pointer type, per POSIX 2008. */ @@ -31,13 +41,23 @@ verify (sizeof NULL == sizeof (void *)); int main (void) { - /* Check that some macros are defined and different integer constants. */ - switch (exitcode) + /* Check subset of <sys/wait.h> macros that must be visible here. + Note that some of these macros are only portable when operating + on an lvalue. */ + int i; + for (i = 0; i < 0x10000; i = (i ? i << 1 : 1)) + if (!!WIFSIGNALED (i) + !!WIFEXITED (i) + !!WIFSTOPPED (i) != 1) + return 1; + i = WEXITSTATUS (i) + WSTOPSIG (i) + WTERMSIG (i); + + switch (i) { - case EXIT_SUCCESS: - case EXIT_FAILURE: +#if 0 + /* Gnulib doesn't guarantee these, yet. */ + case WNOHANG: + case WUNTRACED: +#endif break; } - return 0; } diff --git a/tests/test-sys_wait.c b/tests/test-sys_wait.c index 8c0170e..557aae1 100644 --- a/tests/test-sys_wait.c +++ b/tests/test-sys_wait.c @@ -26,5 +26,26 @@ static pid_t a; int main (void) { - return a; + /* Check for existence of required macros. Note that we document + that these are safe only on lvalues. */ + int i; + for (i = 0; i < 0x10000; i = (i ? i << 1 : 1)) + if (!!WIFSIGNALED (i) + !!WIFEXITED (i) + !!WIFSTOPPED (i) != 1) + return 1; + i = WEXITSTATUS (i) + WSTOPSIG (i) + WTERMSIG (i); + + switch (i) + { +#if 0 + /* Gnulib doesn't guarantee these, yet. */ + case WCONTINUED: + case WNOHANG: + case WUNTRACED: + case WEXITED: + case WNOWAIT: + case WSTOPPED: +#endif + break; + } + return a ? i : 0; } -- 1.7.2.3