This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
locale.c: Work around a z/OS limitation/feature
authorKarl Williamson <khw@cpan.org>
Fri, 11 Dec 2020 21:59:28 +0000 (14:59 -0700)
committerKarl Williamson <khw@cpan.org>
Sat, 12 Dec 2020 15:24:42 +0000 (08:24 -0700)
Without per-thread locales, a multi-thread application is inherently
unsafe.  IBM solves that by allowing you to set up the locale any way
you want, but after you've created a thread, all future locale changes
are ignored, and return failure.

But Perl itself changes the locale in a couple of cases.  Recent changes
have surfaced this issue in one case, leading to a panic.  And this
commit works around it, so that messages will be displayed in the locale
in effect before the threads were created.

The remaining case requires further investigation.  Nothing in our suite
is failing.

locale.c

index bee9c2e..ed3cb66 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -5371,7 +5371,19 @@ Perl_my_strerror(pTHX_ const int errnum)
                 /* The setlocale() just below likely will zap 'save_locale', so
                  * create a copy.  */
                 save_locale = savepv(save_locale);
-                do_setlocale_c(LC_MESSAGES, "C");
+                if (! do_setlocale_c(LC_MESSAGES, "C")) {
+
+                    /* If, for some reason, the locale change failed, we
+                     * soldier on as best as possible under the circumstances,
+                     * using the current locale, and clear save_locale, so we
+                     * don't try to change back.  On z/0S, all setlocale()
+                     * calls fail after you've created a thread.  This is their
+                     * way of making sure the entire process is always a single
+                     * locale.  This means that 'use locale' is always in place
+                     * for messages under these circumstances. */
+                    Safefree(save_locale);
+                    save_locale = NULL;
+                }
             }
         }
     }   /* end of ! within_locale_scope */