From c511845f6226a6da07b3bd00f7c64f81323c8209 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Tue, 20 Sep 2022 07:01:24 -0600 Subject: [PATCH] locale.c: Workaround for attributes.pm breakage See https://github.com/Perl/perl5/issues/20155 The root cause of that problem is that under POSIX 2008, when a thread terminates, it causes thread 0 (the controller) to change to the global locale. Commit a7ff7ac caused perl to pay attention to the environment variables in effect at startup for setting the global locale when using the POSIX 2008 locale API. (Previously only the initial per-thread locale was affected.) This causes problems when the initial setting was for a locale that uses a comma as the radix character, but the thread 0 is set to a locale that is expecting a dot as a radix character. Whenever another thread terminates, thread 0 was silently changed to using the global locake, and hence a comma. This caused parse errors. The real solution is to fix thread 0 to remain in its chosen locale. But that fix is not ready in time for 5.37.4, and it is deemed important to get something working for this monthly development release. This commit changes the initial global LC_NUMERIC locale to always be C, hence uses a dot radix. The vast majority of code is expecting a dot. This is not the ultimate fix, but it works around the immediate problem at hand. The test case is courtesy @bram-perl --- locale.c | 9 +++++++++ t/run/locale.t | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/locale.c b/locale.c index 8a2ee4f0683d..e708f7fd9a74 100644 --- a/locale.c +++ b/locale.c @@ -5011,6 +5011,15 @@ Perl_init_i18nl10n(pTHX_ int printwarn) /* Done with finding the locales; update the auxiliary records */ new_LC_ALL(NULL); +# if defined(USE_POSIX_2008_LOCALE) && defined(USE_LOCALE_NUMERIC) + + /* This is a temporary workaround for #20155, to avoid issues where the + * global locale wants a radix different from the per-thread one. This + * restores behavior for LC_NUMERIC to what it was before a7ff7ac. */ + posix_setlocale(LC_NUMERIC, "C"); + +# endif + for (i = 0; i < NOMINAL_LC_ALL_INDEX; i++) { Safefree(curlocales[i]); } diff --git a/t/run/locale.t b/t/run/locale.t index d42cca9de7ab..3b76ee752ce2 100644 --- a/t/run/locale.t +++ b/t/run/locale.t @@ -449,6 +449,31 @@ EOF EOF "1,5\n2,5", { stderr => 'devnull' }, "Can do math when radix is a comma"); # [perl 115800] + SKIP: { + skip "Perl not compiled with 'useithreads'", 1 if ! $Config{'useithreads'}; + + local $ENV{LC_ALL} = undef; + local $ENV{LC_NUMERIC} = $comma; + fresh_perl_is(<<"EOF", + use threads; + + my \$x = eval "1.25"; + print "\$x", "\n"; # number is ok before thread + my \$str_x = "\$x"; + + my \$thr = threads->create(sub {}); + \$thr->join(); + + print "\$x\n"; # number stringifies the same after thread + + my \$y = eval "1.25"; + print "\$y\n"; # number is ok after threads + print "\$y" eq "\$str_x" || 0; # new number stringifies the same as old number +EOF + "1.25\n1.25\n1.25\n1", { }, "Thread join doesn't disrupt calling thread" + ); # [GH 20155] + } + SKIP: { unless ($have_strtod) { skip("no strtod()", 1);