summaryrefslogtreecommitdiff
path: root/vutil.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2018-02-13 13:12:50 -0700
committerKarl Williamson <khw@cpan.org>2018-02-18 15:44:23 -0700
commit49d7d366441813aa7301b1a437e302372f04f31a (patch)
tree619c3271adeeab23fe9ea25c9517ebf9807cc1fe /vutil.c
parent398eeea9cd1c8a9b95329a3eca8be6a2a5903ac5 (diff)
downloadperl-49d7d366441813aa7301b1a437e302372f04f31a.tar.gz
Latch LC_NUMERIC during critical sections
It is possible for operations on threaded perls which don't 'use locale' to still change the locale. This happens when calling POSIX::localeconv() and I18N::Langinfo(), and in earlier perls, it can happen for other operations when perl has been initialized with the environment causing the various locale categories to not have a uniform locale. This commit causes the areas where the locale for this category should predictably be in one or the other state to be a critical section where another thread can't interrupt and change it. This is a separate mutex, so that only these particular operations will be held up.
Diffstat (limited to 'vutil.c')
-rw-r--r--vutil.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/vutil.c b/vutil.c
index 282da245c8..af5f263be7 100644
--- a/vutil.c
+++ b/vutil.c
@@ -628,6 +628,8 @@ VER_NV:
/* if it isn't C, set it to C. */
const char * locale_name_on_entry;
+ LC_NUMERIC_LOCK(0); /* Start critical section */
+
locale_name_on_entry = setlocale(LC_NUMERIC, NULL);
if ( strNE(locale_name_on_entry, "C")
&& strNE(locale_name_on_entry, "POSIX"))
@@ -638,6 +640,7 @@ VER_NV:
change the locale */
locale_name_on_entry = NULL;
}
+
/* Prevent recursed calls from trying to change back */
LOCK_LC_NUMERIC_STANDARD();
@@ -660,6 +663,9 @@ VER_NV:
if (locale_name_on_entry) {
setlocale(LC_NUMERIC, locale_name_on_entry);
}
+
+ LC_NUMERIC_UNLOCK; /* End critical section */
+
}
#endif /* USE_LOCALE_NUMERIC */