Skip to content

Commit

Permalink
locale.c: localeconv() unconditional NUMERIC toggle
Browse files Browse the repository at this point in the history
It is possible to lockout changing the LC_NUMERIC locale.  This is done
in some printf cases where a recursive call could get the radix
character wrong.  But localeconv(), which could be called during this
recursion on some platforms, toggles the locale briefly, without
affecting the surrounding calls; so it can do the toggle
unconditionally.

The previous commit merely moved the functionality of localeconv() from
POSIX.xs to locale.c.  This commit expands upon that.
  • Loading branch information
khwilliamson committed May 6, 2021
1 parent 73b146d commit 745910a
Showing 1 changed file with 30 additions and 9 deletions.
39 changes: 30 additions & 9 deletions locale.c
Expand Up @@ -3024,19 +3024,31 @@ S_my_localeconv(pTHX)
# elif ! defined(TS_W32_BROKEN_LOCALECONV) /* Next is regular lconv() */

{
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;

/* There are so many locks because localeconv() deals with two
* categories, and returns in a single global static buffer. Some
* locks might be no-ops on this platform, but not others. We need to
* lock if any one isn't a no-op. */
STORE_LC_NUMERIC_FORCE_TO_UNDERLYING();

# ifdef USE_LOCALE_NUMERIC

const char * orig_switched_locale = NULL;

LC_NUMERIC_LOCK(0);
orig_switched_locale = toggle_locale_c(LC_NUMERIC, PL_numeric_name);

# endif

LOCALECONV_LOCK;
retval = copy_localeconv(aTHX_ localeconv(), numeric_locale_is_utf8,
monetary_locale_is_utf8);
LOCALECONV_UNLOCK;
RESTORE_LC_NUMERIC();

# ifdef USE_LOCALE_NUMERIC

restore_toggled_locale_c(LC_NUMERIC, orig_switched_locale);
LC_NUMERIC_UNLOCK;

# endif

return retval;
}
Expand All @@ -3063,11 +3075,15 @@ S_my_localeconv(pTHX)
const char * save_global;
const char * save_thread;
bool restore_per_thread = FALSE;
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;

/* Get to the proper per-thread locale state. (The NUMERIC operations
* are no-ops if not paying attention to LC_NUMERIC) */
STORE_LC_NUMERIC_FORCE_TO_UNDERLYING();
# ifdef USE_LOCALE_NUMERIC

const char * orig_switched_locale = NULL;

LC_NUMERIC_LOCK(0);
orig_switched_locale = toggle_locale_c(LC_NUMERIC, PL_numeric_name);

# endif

/* Save the per-thread locale state */
save_thread = savepv(querylocale_c(LC_ALL));
Expand Down Expand Up @@ -3101,7 +3117,12 @@ S_my_localeconv(pTHX)
/* Restore the per-thread locale state */
void_setlocale_c(LC_ALL, save_thread);

RESTORE_LC_NUMERIC();
# ifdef USE_LOCALE_NUMERIC

restore_toggled_locale_c(LC_NUMERIC, orig_switched_locale);
LC_NUMERIC_UNLOCK;

# endif

Safefree(save_global);
Safefree(save_thread);
Expand Down

0 comments on commit 745910a

Please sign in to comment.