bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

wcrtomb: make multithread-safe


From: Bruno Haible
Subject: wcrtomb: make multithread-safe
Date: Wed, 08 Jan 2020 03:57:11 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-170-generic; KDE/5.18.0; x86_64; ; )

The wcrtomb override is using wctomb(), which is not guaranteed to be
multithread-safe. Better use the original wcrtomb when possible.

It's not possible on IRIX, but I don't want to invest much effort into
this platform now.

Tested on the relevant platforms: 32-bit AIX, HP-UX, IRIX, Solaris 11.3,
MSVC, Android.


2020-01-07  Bruno Haible  <address@hidden>

        wcrtomb: Make multithread-safe, except possibly on IRIX.
        * m4/wcrtomb.m4 (gl_FUNC_WCRTOMB): Don't set REPLACE_WCRTOMB to 1 when
        REPLACE_MBSTATE_T is set. Define WCRTOMB_C_LOCALE_BUG and
        WCRTOMB_RETVAL_BUG.
        * lib/wcrtomb.c (wcrtomb): Use original wcrtomb whenever available. Use
        wctomb only on IRIX.

diff --git a/lib/wcrtomb.c b/lib/wcrtomb.c
index 63d0860..06105f1 100644
--- a/lib/wcrtomb.c
+++ b/lib/wcrtomb.c
@@ -26,6 +26,7 @@
 
 size_t
 wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
+#undef wcrtomb
 {
   /* This implementation of wcrtomb supports only stateless encodings.
      ps must be in the initial state.  */
@@ -35,12 +36,17 @@ wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
       return (size_t)(-1);
     }
 
+#if !HAVE_WCRTOMB                       /* IRIX 6.5 */ \
+    || WCRTOMB_RETVAL_BUG               /* Solaris 11.3, MSVC */ \
+    || WCRTOMB_C_LOCALE_BUG             /* Android */
   if (s == NULL)
     /* We know the NUL wide character corresponds to the NUL character.  */
     return 1;
   else
+#endif
     {
-#if defined __ANDROID__
+#if HAVE_WCRTOMB
+# if WCRTOMB_C_LOCALE_BUG               /* Android */
       /* Implement consistently with mbrtowc(): through a 1:1 correspondence,
          as in ISO-8859-1.  */
       if (wc >= 0 && wc <= 0xff)
@@ -48,17 +54,27 @@ wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
           *s = (unsigned char) wc;
           return 1;
         }
-#else
-      /* Implement on top of wctomb().  */
+      else
+        {
+          errno = EILSEQ;
+          return (size_t)(-1);
+        }
+# else
+      return wcrtomb (s, wc, ps);
+# endif
+#else                                   /* IRIX 6.5 */
+      /* Fallback for platforms that don't have wcrtomb().
+         Implement on top of wctomb().
+         This code is not multithread-safe.  */
       int ret = wctomb (s, wc);
 
       if (ret >= 0)
         return ret;
-#endif
       else
         {
           errno = EILSEQ;
           return (size_t)(-1);
         }
+#endif
     }
 }
diff --git a/m4/wcrtomb.m4 b/m4/wcrtomb.m4
index 64e5110..c45fd98 100644
--- a/m4/wcrtomb.m4
+++ b/m4/wcrtomb.m4
@@ -1,4 +1,4 @@
-# wcrtomb.m4 serial 15
+# wcrtomb.m4 serial 16
 dnl Copyright (C) 2008-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -31,9 +31,11 @@ AC_DEFUN([gl_FUNC_WCRTOMB],
       REPLACE_WCRTOMB=1
     fi
   else
-    if test $REPLACE_MBSTATE_T = 1; then
-      REPLACE_WCRTOMB=1
-    fi
+    dnl We don't actually need to override wcrtomb when redefining the 
semantics
+    dnl of the mbstate_t type. Tested on 32-bit AIX.
+    dnl if test $REPLACE_MBSTATE_T = 1; then
+    dnl   REPLACE_WCRTOMB=1
+    dnl fi
     if test $REPLACE_WCRTOMB = 0; then
       dnl On Android 4.3, wcrtomb produces wrong characters in the C locale.
       dnl On AIX 4.3, OSF/1 5.1 and Solaris <= 11.3, wcrtomb (NULL, 0, NULL)
@@ -79,7 +81,9 @@ int main ()
         ])
       case "$gl_cv_func_wcrtomb_works" in
         *yes) ;;
-        *) REPLACE_WCRTOMB=1 ;;
+        *) AC_DEFINE([WCRTOMB_C_LOCALE_BUG], [1],
+             [Define if the wcrtomb function does not work in the C locale.])
+           REPLACE_WCRTOMB=1 ;;
       esac
     fi
     if test $REPLACE_WCRTOMB = 0; then
@@ -148,7 +152,9 @@ int main ()
         ])
       case "$gl_cv_func_wcrtomb_retval" in
         *yes) ;;
-        *) REPLACE_WCRTOMB=1 ;;
+        *) AC_DEFINE([WCRTOMB_RETVAL_BUG], [1],
+             [Define if the wcrtomb function has an incorrect return value.])
+           REPLACE_WCRTOMB=1 ;;
       esac
     fi
   fi




reply via email to

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