[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] strerror_r-posix: work around cygwin 1.7.9
From: |
Eric Blake |
Subject: |
[PATCH 2/2] strerror_r-posix: work around cygwin 1.7.9 |
Date: |
Tue, 7 Jun 2011 16:32:30 -0600 |
Cygwin __xpg_strerror_r clobbers strerror, until cygwin 1.7.10; in
this case, we must replace strerror, but there was nothing in
strerror.m4 finding fault with cygwin's native strerror. Solve
this by splitting strerror_r.m4 into two parts, one for probing
for the strerror_r bug, and one for replacing strerror_r based
on the presence of bugs unrelated to signature issues; that way,
the 'strerror' module in isolation will not replace strerror, but
if strerror_r is in use for any other reason, then the two use
separate buffers.
Note that cygwin's strerror is thread-safe while the gnulib
replacement is not; but this is no worse than any other
platform where strerror is not thread-safe; in a single-threaded
program, the difference is not observable, and in a multi-threaded
program, you really shouldn't be using strerror in the first place.
Also note that this ends up replacing glibc 2.13 strerror as it
deems __xpg_strerror_r broken on that platform, which isn't
technically necessary for strerror, but doesn't hurt too much.
Meanwhile, glibc 2.14 fixed __xpg_strerror_r, and strerror is not
replaced in that scenario.
* m4/strerror_r.m4 (gl_FUNC_STRERROR_R): Split...
(gl_FUNC_STRERROR_R_WORKS): ...into new macro, to detect Cygwin
bug without replacing strerror_r.
* m4/strerror.m4 (gl_FUNC_STRERROR): Replace strerror if
strerror_r is buggy, but without requiring strerror_r compilation.
* doc/posix-functions/strerror_r.texi (strerror_r): Fix docs.
Signed-off-by: Eric Blake <address@hidden>
---
Tested on cygwin 1.7.9 and glibc 2.13:
strerror in isolation - no replacements
strerror_r-posix in isolation - strerror_r replaced
perror, strerror, strerror_r-posix together - strerror and strerror_r
replaced, all tests pass
and on cygwin CVS (will become 1.7.10) and glibc 2.14:
strerror in isolation - no replacements
strerror_r-posix in isolation - strerror_r replaced
perror, strerror, strerror_r-posix together - only strerror_r
replaced, all tests pass
Committing this requires that Bruno's fix for strerror to move
AC_LIBOBJ to the modules file already be applied, so I've
pushed that one (as well as the trivial modules/perror change)
in the process.
Now to go investigate the MacOS failures...
ChangeLog | 8 +++
doc/posix-functions/strerror_r.texi | 4 --
m4/strerror.m4 | 9 +++-
m4/strerror_r.m4 | 90 +++++++++++++++++++++++++++--------
4 files changed, 86 insertions(+), 25 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 870ec73..af21155 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2011-06-07 Eric Blake <address@hidden>
+ strerror_r-posix: work around cygwin 1.7.9
+ * m4/strerror_r.m4 (gl_FUNC_STRERROR_R): Split...
+ (gl_FUNC_STRERROR_R_WORKS): ...into new macro, to detect Cygwin
+ bug without replacing strerror_r.
+ * m4/strerror.m4 (gl_FUNC_STRERROR): Replace strerror if
+ strerror_r is buggy, but without requiring strerror_r compilation.
+ * doc/posix-functions/strerror_r.texi (strerror_r): Fix docs.
+
test-perror: relax test to ignore cygwin bug
* tests/test-perror2.c (main): Relax test on requiring detection
of stream errors, and use unbuffered stream.
diff --git a/doc/posix-functions/strerror_r.texi
b/doc/posix-functions/strerror_r.texi
index e0f19c0..4169ca9 100644
--- a/doc/posix-functions/strerror_r.texi
+++ b/doc/posix-functions/strerror_r.texi
@@ -64,8 +64,4 @@ strerror_r
Portability problems not fixed by Gnulib:
@itemize
address@hidden
-Calling this function can clobber the buffer used by @code{strerror}
-on some platforms:
-Cygwin 1.7.9.
@end itemize
diff --git a/m4/strerror.m4 b/m4/strerror.m4
index 25edd91..de4ba96 100644
--- a/m4/strerror.m4
+++ b/m4/strerror.m4
@@ -1,4 +1,4 @@
-# strerror.m4 serial 12
+# strerror.m4 serial 13
dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -8,6 +8,9 @@ AC_DEFUN([gl_FUNC_STRERROR],
[
AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
AC_REQUIRE([gl_HEADER_ERRNO_H])
+ m4_ifdef([gl_FUNC_STRERROR_R_WORKS], [
+ AC_REQUIRE([gl_FUNC_STRERROR_R_WORKS])
+ ])
if test -z "$ERRNO_H"; then
AC_CACHE_CHECK([for working strerror function],
[gl_cv_func_working_strerror],
@@ -32,6 +35,10 @@ AC_DEFUN([gl_FUNC_STRERROR],
dnl integers. Replace it.
REPLACE_STRERROR=1
fi
+ dnl If the system's strerror_r clobbers strerror, we must replace strerror.
+ case $gl_cv_func_strerror_r_works in
+ *no) REPLACE_STRERROR=1 ;;
+ esac
else
dnl The system's strerror() cannot know about the new errno values we add
dnl to <errno.h>. Replace it.
diff --git a/m4/strerror_r.m4 b/m4/strerror_r.m4
index 1c0af36..c1d1a8e 100644
--- a/m4/strerror_r.m4
+++ b/m4/strerror_r.m4
@@ -1,4 +1,4 @@
-# strerror_r.m4 serial 9
+# strerror_r.m4 serial 10
dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -6,9 +6,7 @@ dnl with or without modifications, as long as this notice is
preserved.
AC_DEFUN([gl_FUNC_STRERROR_R],
[
- AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
- AC_REQUIRE([gl_HEADER_ERRNO_H])
- AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_REQUIRE([gl_FUNC_STRERROR_R_WORKS])
dnl Persuade Solaris <string.h> to declare strerror_r().
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
@@ -20,7 +18,40 @@ AC_DEFUN([gl_FUNC_STRERROR_R],
HAVE_DECL_STRERROR_R=0
fi
- AC_CHECK_FUNCS([strerror_r])
+ if test $ac_cv_func_strerror_r = yes; then
+ if test -z "$ERRNO_H"; then
+ if test $gl_cv_func_strerror_r_posix_signature = yes; then
+ case "$gl_cv_func_strerror_r_works" in
+ dnl The system's strerror_r has bugs. Replace it.
+ *no) REPLACE_STRERROR_R=1 ;;
+ esac
+ else
+ dnl The system's strerror() has a wrong signature. Replace it.
+ REPLACE_STRERROR_R=1
+ fi
+ else
+ dnl The system's strerror_r() cannot know about the new errno values we
+ dnl add to <errno.h>. Replace it.
+ REPLACE_STRERROR_R=1
+ fi
+ fi
+])
+
+# Prerequisites of lib/strerror_r.c.
+AC_DEFUN([gl_PREREQ_STRERROR_R], [
+ AC_CHECK_FUNCS_ONCE([catgets])
+ :
+])
+
+# Detect if strerror_r works, but without affecting whether a replacement
+# strerror_r will be used.
+AC_DEFUN([gl_FUNC_STRERROR_R_WORKS],
+[
+ AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+ AC_REQUIRE([gl_HEADER_ERRNO_H])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ AC_CHECK_FUNCS_ONCE([strerror_r])
if test $ac_cv_func_strerror_r = yes; then
if test -z "$ERRNO_H"; then
dnl The POSIX prototype is: int strerror_r (int, char *, size_t);
@@ -85,25 +116,44 @@ changequote(,)dnl
changequote([,])dnl
])
])
- case "$gl_cv_func_strerror_r_works" in
- *no) REPLACE_STRERROR_R=1 ;;
- esac
else
- dnl The system's strerror() has a wrong signature. Replace it.
- REPLACE_STRERROR_R=1
+ dnl The system's strerror() has a wrong signature.
dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
AC_CHECK_FUNCS([__xpg_strerror_r])
+ dnl glibc < 2.14 does not populate buf on failure
+ dnl cygwin < 1.7.10 clobbers strerror
+ if test $ac_cv_func___xpg_strerror_r = yes; then
+ AC_CACHE_CHECK([whether strerror_r works],
+ [gl_cv_func_strerror_r_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <errno.h>
+ #include <string.h>
+ extern int __xpg_strerror_r(int, char *, size_t);
+ ]],
+ [[int result = 0;
+ char buf[256] = "^";
+ char copy[256];
+ char *str = strerror (-1);
+ strcpy (copy, str);
+ if (__xpg_strerror_r (-2, buf, 1) == 0)
+ result |= 1;
+ if (*buf)
+ result |= 2;
+ __xpg_strerror_r (-2, buf, 256);
+ if (strcmp (str, copy))
+ result |= 4;
+ return result;
+ ]])],
+ [gl_cv_func_strerror_r_works=yes],
+ [gl_cv_func_strerror_r_works=no],
+ [dnl guess no on all platforms that have __xpg_strerror_r,
+ dnl at least until fixed glibc and cygwin are more common
+ gl_cv_func_strerror_r_works="guessing no"
+ ])
+ ])
+ fi
fi
- else
- dnl The system's strerror_r() cannot know about the new errno values we
- dnl add to <errno.h>. Replace it.
- REPLACE_STRERROR_R=1
fi
fi
])
-
-# Prerequisites of lib/strerror_r.c.
-AC_DEFUN([gl_PREREQ_STRERROR_R], [
- AC_CHECK_FUNCS_ONCE([catgets])
- :
-])
--
1.7.4.4