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 <br...@clisp.org> 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