bug-gnulib
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]