Don't create locale object unless threaded
authorKarl Williamson <khw@cpan.org>
Fri, 9 Mar 2018 19:06:30 +0000 (12:06 -0700)
committerKarl Williamson <khw@cpan.org>
Mon, 12 Mar 2018 16:22:01 +0000 (10:22 -0600)
PL_C_locale_obj is now only created on threaded builds on systems with
POSIX 2008.  On unthreaded builds, we really should continue to use the
old tried and true library calls.

locale.c
makedef.pl
perl.c
perl.h
perlvars.h

index 277e038..e58fb3b 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -3110,7 +3110,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
 
 #    endif
 #  endif
-#  if defined(LC_ALL_MASK) && defined(HAS_POSIX_2008_LOCALE)
+#  ifdef USE_POSIX_2008_LOCALE
 
     PL_C_locale_obj = newlocale(LC_ALL_MASK, "C", (locale_t) 0);
     if (! PL_C_locale_obj) {
@@ -4875,19 +4875,31 @@ Perl_my_strerror(pTHX_ const int errnum)
 
     const bool within_locale_scope = IN_LC(LC_MESSAGES);
 
-#  if defined(HAS_POSIX_2008_LOCALE) && defined(HAS_STRERROR_L)
+#  ifndef USE_ITHREADS
 
-    /* This function is trivial if we don't have to worry about thread safety
-     * and have strerror_l(), as it handles the switch of locales so we don't
-     * have to deal with that.  We don't have to worry about thread safety if
-     * this is an unthreaded build, or if strerror_r() is also available.  Both
-     * it and strerror_l() are thread-safe.  Plain strerror() isn't thread
-     * safe.  But on threaded builds when strerror_r() is available, the
-     * apparent call to strerror() below is actually a macro that
-     * behind-the-scenes calls strerror_r().
-     */
+    /* This function is trivial without threads. */
+    if (within_locale_scope) {
+        errstr = savepv(strerror(errnum));
+    }
+    else {
+        const char * save_locale = do_setlocale_c(LC_MESSAGES, NULL);
+
+        do_setlocale_c(LC_MESSAGES, "C");
+        errstr = savepv(strerror(errnum));
+        do_setlocale_c(LC_MESSAGES, save_locale);
+    }
+
+#  elif defined(HAS_POSIX_2008_LOCALE) && defined(HAS_STRERROR_L)
+
+    /* This function is also trivial if we don't have to worry about thread
+     * safety and have strerror_l(), as it handles the switch of locales so we
+     * don't have to deal with that.  We don't have to worry about thread
+     * safety if strerror_r() is also available.  Both it and strerror_l() are
+     * thread-safe.  Plain strerror() isn't thread safe.  But on threaded
+     * builds when strerror_r() is available, the apparent call to strerror()
+     * below is actually a macro that behind-the-scenes calls strerror_r(). */
 
-#    if ! defined(USE_ITHREADS) || defined(HAS_STRERROR_R)
+#    ifdef HAS_STRERROR_R
 
     if (within_locale_scope) {
         errstr = savepv(strerror(errnum));
index 626d990..f2b4684 100644 (file)
@@ -398,6 +398,7 @@ unless ($define{'USE_ITHREADS'}) {
                    Perl_stashpv_hvname_match
                    Perl_regdupe_internal
                    Perl_newPADOP
+                    PL_C_locale_obj
                         );
 }
 
diff --git a/perl.c b/perl.c
index 1bc15a0..f894780 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -470,7 +470,7 @@ perl_construct(pTHXx)
     /* Start with 1 bucket, for DFS.  It's unlikely we'll need more.  */
     HvMAX(PL_registered_mros) = 0;
 
-#ifdef HAS_POSIX_2008_LOCALE
+#ifdef USE_POSIX_2008_LOCALE
     PL_C_locale_obj = newlocale(LC_ALL_MASK, "C", NULL);
 #endif
 
diff --git a/perl.h b/perl.h
index dd81d62..3a8a29f 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -5643,9 +5643,7 @@ typedef struct am_table_short AMTS;
 #endif
 
 #ifdef USE_LOCALE /* These locale things are all subject to change */
-    /* We create a C locale object unconditionally if we have the functions to
-     * do so; hence must destroy it unconditionally at the end */
-#  ifndef HAS_POSIX_2008_LOCALE
+#  ifndef USE_POSIX_2008_LOCALE
 #    define _LOCALE_TERM_POSIX_2008  NOOP
 #  else
 #    define _LOCALE_TERM_POSIX_2008                                         \
index 0f2e347..d327583 100644 (file)
@@ -105,11 +105,7 @@ PERLVAR(G, lc_numeric_mutex, perl_mutex)   /* Mutex for switching LC_NUMERIC */
 #  endif
 #endif
 
-/* Proxy for HAS_POSIX_2008_LOCALE, since that is not defined in time for this */
-#if   defined(HAS_NEWLOCALE)                    \
- &&   defined(HAS_FREELOCALE)                   \
- &&   defined(HAS_USELOCALE)                    \
- && ! defined(NO_POSIX_2008_LOCALE)
+#ifdef USE_POSIX_2008_LOCALE
 PERLVAR(G, C_locale_obj, locale_t)
 #endif