summaryrefslogtreecommitdiff
path: root/locale.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2019-11-27 19:15:11 -0700
committerKarl Williamson <khw@cpan.org>2019-11-30 12:08:18 -0700
commit45cef8fb80248a6318f90219499ff2dbd953ae8c (patch)
tree28d06dd372781f9e74576830f146e1619f1e9074 /locale.c
parentdf6bd76f98839f1564209d4723f1b8599e14b2f9 (diff)
downloadperl-45cef8fb80248a6318f90219499ff2dbd953ae8c.tar.gz
PATCH: GH #17081: Workaround glibc bug with LC_MESSAGES
Please see the ticket for a full explanation. This bug has been submitted to glibc, without any real action forthcoming so far. This invalidates the message cache each time the locale of LC_MESSAGES is changed, as glibc should be doing this when uselocale changes that, but glibc fails to do so. This patch is an extension to the one submitted by Niko Tyni++. I don't know how to test it, since a test would rely on several different locales in different languages being available, and that depends on what's installed on the platform. I suppose that one could go through the available locales, and try to find three with different wording for the same message. Doing so however would trigger the bug, and at the end, if we didn't get three that differed, we wouldn't know we wouldn't know if it is because of the bug, or that they just didn't exist on the system. However, below is a perl program that demonstrated the patch worked. You could adjust it to the available locales. The buggy code shows the same text for all locales. The fixed shows three different languages. use strict; use Locale::gettext; use POSIX; $ENV{LANG} = 'C.UTF-8'; for my $lang (qw(fi_FI fr_FR en_US)) { $ENV{LANGUAGE} = $lang; setlocale(LC_MESSAGES, ''); my $d = Locale::gettext->domain("bash"); print $d->get('syntax error'), "\n"; }
Diffstat (limited to 'locale.c')
-rw-r--r--locale.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/locale.c b/locale.c
index cdf125cee5..7ce7b3ed4c 100644
--- a/locale.c
+++ b/locale.c
@@ -402,6 +402,7 @@ S_category_name(const int category)
* known at compile time; "do_setlocale_r", not known until run time */
# define do_setlocale_c(cat, locale) my_setlocale(cat, locale)
# define do_setlocale_r(cat, locale) my_setlocale(cat, locale)
+# define FIX_GLIBC_LC_MESSAGES_BUG(i)
#else /* Below uses POSIX 2008 */
@@ -415,6 +416,22 @@ S_category_name(const int category)
emulate_setlocale(cat, locale, cat ## _INDEX, TRUE)
# define do_setlocale_r(cat, locale) emulate_setlocale(cat, locale, 0, FALSE)
+# if ! defined(__GLIBC__) || ! defined(USE_LOCALE_MESSAGES)
+
+# define FIX_GLIBC_LC_MESSAGES_BUG(i)
+
+# else /* Invalidate glibc cache of loaded translations, see [perl #134264] */
+
+# include <libintl.h>
+# define FIX_GLIBC_LC_MESSAGES_BUG(i) \
+ STMT_START { \
+ if ((i) == LC_MESSAGES_INDEX) { \
+ textdomain(textdomain(NULL)); \
+ } \
+ } STMT_END
+
+# endif
+
/* A third array, parallel to the ones above to map from category to its
* equivalent mask */
const int category_masks[] = {
@@ -1158,6 +1175,8 @@ S_emulate_setlocale(const int category,
Safefree(PL_curlocales[i]);
PL_curlocales[i] = savepv(locale);
}
+
+ FIX_GLIBC_LC_MESSAGES_BUG(LC_MESSAGES_INDEX);
}
else {
@@ -1172,6 +1191,8 @@ S_emulate_setlocale(const int category,
/* Then update the category's record */
Safefree(PL_curlocales[index]);
PL_curlocales[index] = savepv(locale);
+
+ FIX_GLIBC_LC_MESSAGES_BUG(index);
}
# endif