Skip to content

Conversation

@henderkes
Copy link
Contributor

@henderkes henderkes commented Nov 19, 2025

It's documented at https://www.php.net/manual/en/function.setlocale.php that the setlocale php function is not thread locale (and actually, not thread safe, because the C setlocale function is MT-unsafe). This leads to very unexpected behaviour in FrankenPHP.

I would therefore like to propose changing setlocale to use POSIX uselocale instead.
Unfortunately, because querylocale is only available on BSD, this adds a lot of string caching logic to let users query for current locales, as I'm not aware of a different way. Perhaps you can give me some pointers to avoid this logic.

The logic for windows remains unchanged.

See: php/frankenphp#1941

Given the following PHP code to simulate different FrankenPHP requests:

<?php
use parallel\Runtime;

setlocale(LC_ALL,'C');
echo "main@start   : ".setlocale(LC_ALL,0)." | dp=".localeconv()['decimal_point']."\n";

$f = (new Runtime())->run(function () {
    setlocale(LC_ALL,'de_DE.UTF-8');
    echo "worker@set   : ".setlocale(LC_ALL,0)." | dp=".localeconv()['decimal_point']."\n";
});

echo "main@after   : ".setlocale(LC_ALL,0)." | dp=".localeconv()['decimal_point']."\n";

$f->value();

Currently:

[m@M bin]$ php -d "extension=/home/m/static-php-cli/buildroot/modules/parallel.so" localetest.php 
main@start   : C.UTF-8 | dp=.
worker@set   : de_DE.UTF-8 | dp=,
main@after   : de_DE.UTF-8 | dp=,

Expected, after proposed implementation:

[m@M bin]$ ./php -d "extension=/home/m/static-php-cli/buildroot/modules/parallel.so" localetest.php 
main@start   : C.UTF-8 | dp=.
worker@set   : de_DE.UTF-8 | dp=,
main@after   : C.UTF-8 | dp=.

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frankly, I'd rather try to push people away from using setlocale() by recommending them to use ICU related functionality rather than relying on the OS locales behaving properly.

BG(ctype_string) = NULL;
return ZSTR_CHAR('C');
} else if (zend_string_equals_cstr(loc, retval, len)) {
} else if (zend_string_equals_cstr(loc, ZSTR_VAL(ret_str), ZSTR_LEN(ret_str))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} else if (zend_string_equals_cstr(loc, ZSTR_VAL(ret_str), ZSTR_LEN(ret_str))) {
} else if (zend_string_equals(loc, ret_str)) {

@henderkes
Copy link
Contributor Author

I would also be fine with deprecating setlocale(), would avoid this string mess as well. I just don't believe there should be functions in a ZTS build that can crash the process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants