diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index f35d196fb971..ffceabd88220 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -18,8 +18,8 @@ #include #ifdef ZTS -#include "ext/standard/php_string.h" /* for localeconv_r() */ -#define LCONV_DECIMAL_POINT (*lconv.decimal_point) +#include "ext/standard/php_string.h" /* for localeconv_decimal_point() */ +#define LCONV_DECIMAL_POINT localeconv_decimal_point() #else #define LCONV_DECIMAL_POINT (*lconv->decimal_point) #endif @@ -221,9 +221,7 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos, char *s = NULL; size_t s_len = 0; bool is_negative = false; -#ifdef ZTS - struct lconv lconv; -#else +#ifndef ZTS struct lconv *lconv; #endif @@ -256,9 +254,7 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos, case 'E': case 'f': case 'F': -#ifdef ZTS - localeconv_r(&lconv); -#else +#ifndef ZTS lconv = localeconv(); #endif s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision, @@ -285,9 +281,7 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos, char decimal_point = '.'; if (fmt == 'g' || fmt == 'G') { -#ifdef ZTS - localeconv_r(&lconv); -#else +#ifndef ZTS lconv = localeconv(); #endif decimal_point = LCONV_DECIMAL_POINT; diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 86c331f8a7c5..412a4a4fa7a6 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -32,6 +32,9 @@ PHP_MINIT_FUNCTION(string_intrin); strnatcmp_ex(a, strlen(a), b, strlen(b), true) PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, bool is_case_insensitive); PHPAPI struct lconv *localeconv_r(struct lconv *out); +#ifdef ZTS +PHPAPI char localeconv_decimal_point(void); +#endif PHPAPI char *php_strtr(char *str, size_t len, const char *str_from, const char *str_to, size_t trlen); PHPAPI zend_string *php_addslashes(zend_string *str); PHPAPI void php_stripslashes(zend_string *str); diff --git a/ext/standard/string.c b/ext/standard/string.c index c6e89dcca2e5..87e667392104 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -19,6 +19,9 @@ #include "php_string.h" #include "php_variables.h" #include +#ifdef HAVE_NL_LANGINFO +# include +#endif #ifdef HAVE_LANGINFO_H # include #endif @@ -88,6 +91,20 @@ static zend_string *php_hex2bin(const unsigned char *old, const size_t oldlen) } /* }}} */ +#ifdef ZTS +/* read the decimal point through nl_langinfo() (thread-safe), instead of taking the lock. */ +PHPAPI char localeconv_decimal_point(void) +{ +#if defined(HAVE_NL_LANGINFO) && (defined(__GLIBC__) || defined(__MUSL__)) + return *nl_langinfo(RADIXCHAR); +#else + struct lconv lc; + localeconv_r(&lc); + return *lc.decimal_point; +#endif +} +#endif + /* {{{ localeconv_r * glibc's localeconv is not reentrant, so lets make it so ... sorta */ PHPAPI struct lconv *localeconv_r(struct lconv *out) diff --git a/main/snprintf.c b/main/snprintf.c index 73c981a1cee7..9e9655fb70ad 100644 --- a/main/snprintf.c +++ b/main/snprintf.c @@ -30,7 +30,7 @@ #include #ifdef ZTS #include "ext/standard/php_string.h" -#define LCONV_DECIMAL_POINT (*lconv.decimal_point) +#define LCONV_DECIMAL_POINT localeconv_decimal_point() #else #define LCONV_DECIMAL_POINT (*lconv->decimal_point) #endif @@ -491,9 +491,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ char num_buf[NUM_BUF_SIZE]; char char_buf[2]; /* for printing %% and % */ -#ifdef ZTS - struct lconv lconv; -#else +#ifndef ZTS struct lconv *lconv = NULL; #endif @@ -843,9 +841,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ s = "INF"; s_len = 3; } else { -#ifdef ZTS - localeconv_r(&lconv); -#else +#ifndef ZTS if (!lconv) { lconv = localeconv(); } @@ -902,9 +898,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ /* * * We use &num_buf[ 1 ], so that we have room for the sign */ -#ifdef ZTS - localeconv_r(&lconv); -#else +#ifndef ZTS if (!lconv) { lconv = localeconv(); } diff --git a/main/spprintf.c b/main/spprintf.c index 6553853d8104..74d2b43cc4f3 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -88,7 +88,7 @@ #include #ifdef ZTS #include "ext/standard/php_string.h" -#define LCONV_DECIMAL_POINT (*lconv.decimal_point) +#define LCONV_DECIMAL_POINT localeconv_decimal_point() #else #define LCONV_DECIMAL_POINT (*lconv->decimal_point) #endif @@ -196,9 +196,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ char num_buf[NUM_BUF_SIZE]; char char_buf[2]; /* for printing %% and % */ -#ifdef ZTS - struct lconv lconv; -#else +#ifndef ZTS struct lconv *lconv = NULL; #endif @@ -556,9 +554,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ s = "inf"; s_len = 3; } else { -#ifdef ZTS - localeconv_r(&lconv); -#else +#ifndef ZTS if (!lconv) { lconv = localeconv(); } @@ -614,9 +610,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ /* * * We use &num_buf[ 1 ], so that we have room for the sign */ -#ifdef ZTS - localeconv_r(&lconv); -#else +#ifndef ZTS if (!lconv) { lconv = localeconv(); }