summaryrefslogtreecommitdiff
path: root/ext/POSIX/POSIX.xs
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2018-01-17 13:32:32 -0700
committerKarl Williamson <khw@cpan.org>2018-01-31 06:57:50 -0700
commit7d5966ae3c3b8f0e43fa09554a46cb8de9c98f5f (patch)
treec49c3bceab87d754e6e1d57c1acef50068ee4cbc /ext/POSIX/POSIX.xs
parent6e4200280cd1c3843eea21c73aab78a8c7063027 (diff)
downloadperl-7d5966ae3c3b8f0e43fa09554a46cb8de9c98f5f.tar.gz
POSIX::localconv(): Prefer localeconv_l()
This is a thread-safe version of localeconv(), so use it under threads.
Diffstat (limited to 'ext/POSIX/POSIX.xs')
-rw-r--r--ext/POSIX/POSIX.xs29
1 files changed, 26 insertions, 3 deletions
diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs
index 0ab9470832..1dbcd076e4 100644
--- a/ext/POSIX/POSIX.xs
+++ b/ext/POSIX/POSIX.xs
@@ -2124,7 +2124,12 @@ localeconv()
localeconv(); /* A stub to call not_here(). */
#else
struct lconv *lcbuf;
-
+# if defined(USE_ITHREADS) \
+ && defined(HAS_POSIX_2008_LOCALE) \
+ && defined(HAS_LOCALECONV_L) /* Prefer this thread-safe version */
+ bool do_free = FALSE;
+ locale_t cur = uselocale((locale_t) 0);
+# endif
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
/* localeconv() deals with both LC_NUMERIC and LC_MONETARY, but
@@ -2144,11 +2149,22 @@ localeconv()
RETVAL = newHV();
sv_2mortal((SV*)RETVAL);
+# if defined(USE_ITHREADS) \
+ && defined(HAS_POSIX_2008_LOCALE) \
+ && defined(HAS_LOCALECONV_L)
+
+ if (cur == LC_GLOBAL_LOCALE) {
+ cur = duplocale(LC_GLOBAL_LOCALE);
+ do_free = TRUE;
+ }
+ lcbuf = localeconv_l(cur);
+# else
LOCALE_LOCK; /* Prevent interference with other threads using
localeconv() */
- lcbuf = localeconv();
+ lcbuf = localeconv();
+# endif
if (lcbuf) {
const struct lconv_offset *strings = lconv_strings;
const struct lconv_offset *integers = lconv_integers;
@@ -2199,8 +2215,15 @@ localeconv()
integers++;
}
}
-
+# if defined(USE_ITHREADS) \
+ && defined(HAS_POSIX_2008_LOCALE) \
+ && defined(HAS_LOCALECONV_L)
+ if (do_free) {
+ freelocale(cur);
+ }
+# else
LOCALE_UNLOCK;
+# endif
RESTORE_LC_NUMERIC();
#endif /* HAS_LOCALECONV */
OUTPUT: