The first application of the 'setlocale-null' module is to fix the duplocale() replacement.
2019-12-15 Bruno Haible <br...@clisp.org> duplocale: Fix multithread-safety bug on AIX. * lib/duplocale.c: Don't include <stdlib.h>. (rpl_duplocale): Invoke setlocale_null instead of setlocale. * m4/duplocale.m4 (gl_FUNC_DUPLOCALE): Require gl_FUNC_SETLOCALE_NULL. Set LIB_DUPLOCALE. * modules/duplocale (Depends-on): Add setlocale-null. (Link): New section. * modules/duplocale-tests (Makefile.am): Link test-duplocale with $(LIB_DUPLOCALE). diff --git a/lib/duplocale.c b/lib/duplocale.c index 3b958ba..d22a447 100644 --- a/lib/duplocale.c +++ b/lib/duplocale.c @@ -22,7 +22,6 @@ #include <locale.h> #include <errno.h> -#include <stdlib.h> #include <string.h> #define SIZEOF(a) (sizeof(a) / sizeof(a[0])) @@ -68,27 +67,33 @@ rpl_duplocale (locale_t locale) , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK } #endif }; - char *base_name; + char base_name[SETLOCALE_NULL_MAX]; + int err; locale_t base_copy; unsigned int i; - base_name = strdup (setlocale (LC_CTYPE, NULL)); - if (base_name == NULL) - return NULL; - base_copy = newlocale (LC_ALL_MASK, base_name, NULL); - if (base_copy == NULL) + err = setlocale_null (LC_CTYPE, base_name, sizeof (base_name)); + if (err) { - int saved_errno = errno; - free (base_name); - errno = saved_errno; + errno = err; return NULL; } + base_copy = newlocale (LC_ALL_MASK, base_name, NULL); + if (base_copy == NULL) + return NULL; for (i = 0; i < SIZEOF (categories); i++) { int category = categories[i].cat; int category_mask = categories[i].mask; - const char *name = setlocale (category, NULL); + char name[SETLOCALE_NULL_MAX]; + + err = setlocale_null (category, name, sizeof (name)); + if (err) + { + errno = err; + return NULL; + } if (strcmp (name, base_name) != 0) { locale_t copy = newlocale (category_mask, name, base_copy); @@ -96,7 +101,6 @@ rpl_duplocale (locale_t locale) { int saved_errno = errno; freelocale (base_copy); - free (base_name); errno = saved_errno; return NULL; } @@ -106,7 +110,6 @@ rpl_duplocale (locale_t locale) } } - free (base_name); return base_copy; } diff --git a/m4/duplocale.m4 b/m4/duplocale.m4 index fb5e602..3900b53 100644 --- a/m4/duplocale.m4 +++ b/m4/duplocale.m4 @@ -1,4 +1,4 @@ -# duplocale.m4 serial 11 +# duplocale.m4 serial 12 dnl Copyright (C) 2009-2019 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,7 @@ AC_DEFUN([gl_FUNC_DUPLOCALE], [ AC_REQUIRE([gl_LOCALE_H_DEFAULTS]) AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([gl_FUNC_SETLOCALE_NULL]) AC_CHECK_FUNCS_ONCE([duplocale]) if test $ac_cv_func_duplocale = yes; then dnl Check against glibc bug where duplocale crashes. @@ -109,6 +110,12 @@ int main () else HAVE_DUPLOCALE=0 fi + if test $REPLACE_DUPLOCALE = 1; then + LIB_DUPLOCALE="$LIB_SETLOCALE_NULL" + else + LIB_DUPLOCALE= + fi + AC_SUBST([LIB_DUPLOCALE]) ]) # Prerequisites of lib/duplocale.c. diff --git a/modules/duplocale b/modules/duplocale index 08eca3c..aaa12cd 100644 --- a/modules/duplocale +++ b/modules/duplocale @@ -7,6 +7,7 @@ m4/duplocale.m4 Depends-on: locale +setlocale-null [test $REPLACE_DUPLOCALE = 1] configure.ac: gl_FUNC_DUPLOCALE @@ -21,6 +22,9 @@ Makefile.am: Include: <locale.h> +Link: +$(LIB_DUPLOCALE) + License: LGPL diff --git a/modules/duplocale-tests b/modules/duplocale-tests index 29b2a1a..6545c4e 100644 --- a/modules/duplocale-tests +++ b/modules/duplocale-tests @@ -15,3 +15,4 @@ gt_FUNC_USELOCALE Makefile.am: TESTS += test-duplocale check_PROGRAMS += test-duplocale +test_duplocale_LDADD = $(LDADD) @LIB_DUPLOCALE@