perl5
perl5 copied to clipboard
win32/locale: Fallback to 'system default locale' is broken
Description: In commit 65ebb05984db179833ff252f547043f32184d893 (included in perl v5.20.0) a fallback to the 'system default locale' was added for Windows. In commit d2b24094d5f9c39457520a4a1ecbabb9e3999245 (included in perl v5.28.0) this however got (accidentally) broken.
Example (using Strawberry Perl):
set LC_ALL=foo
set LANG=bar
.\5.18.4\perl\bin\perl.exe -e1
.\5.20.3\perl\bin\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = "foo",
LANG = "bar"
are supported and installed on your system.
perl: warning: Falling back to the system default locale ("English_Belgium.1252").
.\5.26.3\perl\bin\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = "foo",
LANG = "bar"
are supported and installed on your system.
perl: warning: Falling back to the system default locale ("English_Belgium.1252").
.\5.28.2\perl\bin\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = "foo",
LANG = "bar"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
TLDR:
- no warning/fallback on 5.18.4
- fallback to 'system default locale' for v5.20.0 - v5.26.3
- fallback to 'standard locale' for v5.28.0+
Steps to reproduce:
On windows set to env variable LC_ALL and LANG to an invalid value and then run perl -e1
i.e.
set LC_ALL=fooset LANG=barperl -e1
Expected result:
Warning message shows Falling back to the system default locale (...)
The bug:
On Windows calling setlocale(LC_ALL, "") returns the default environment.
This is what the code attempts to do.
In the original commit:
system_default_locale = setlocale(LC_ALL, "");
Today that same code:
system_default_locale = setlocale_c(LC_ALL, "");
On WIN32 setlocale_c resolves to S_win32_setlocale which contains (stripped down version):
if (locale && strEQ(locale, "")) {
locale = PerlEnv_getenv("LC_ALL");
}
#ifdef USE_WSETLOCALE
result = S_wrap_wsetlocale(aTHX_ category, locale);
#else
result = setlocale(category, locale);
#endif
In other words: to set system_default_locale the code needs to call setlocale with an empty string but S_win32_setlocale checks for the empty string and then changes it.
Which causes setlocale to not be called with the empty string causing system_default_locale to end up as NULL.
Possible fix:
A possible quick and dirty fix is to bypass S_win32_setlocale and instead call setlocale directly:
diff --git a/locale.c b/locale.c
index 88583a0ef2..b2717d1ebc 100644
--- a/locale.c
+++ b/locale.c
@@ -3500,7 +3500,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
/* Note that this may change the locale, but we are going to do
* that anyway just below */
- system_default_locale = setlocale_c(LC_ALL, "");
+ system_default_locale = setlocale(LC_ALL, "");
DEBUG_LOCALE_INIT(LC_ALL_INDEX_, "", system_default_locale);
/* Skip if invalid or if it's already on the list of locales to
Before the patch:
.\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = "foo",
(possibly more locale environment variables)
LANG = "bar"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
After the patch:
.\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = "foo",
(possibly more locale environment variables)
LANG = "bar"
are supported and installed on your system.
perl: warning: Falling back to the system default locale ("English_Belgium.1252").