Perl 5.27.9 gives threads their own locales
Perl 5.27.9 uses native thread-safe locale operations and exposes a capability flag, with explicit limits for extensions and unsupported platforms.
Locale settings can affect a thread that never asked to change them when the settings belong to the whole process. Perl 5.27.9 changes this arrangement on systems with suitable native support. Its release notes say that locale changes now affect only the calling thread on supported platforms. The same release introduces ${^SAFE_LOCALES}, a read-only variable that reports whether safe locale operations are available to the interpreter.
The release history included in the tag dates 5.27.9 to February 20. This is development work, and the documentation describes the resulting behaviour as part of the coming 5.28 interface. The immediate subject is the implementation available in this development release, including the boundary between Perl code and native extensions.
I value Perl for text work, where locale-dependent behaviour can be part of the actual computation. Treating a locale change as a thread-local operation makes that computation easier to reason about. It also makes the platform dependency worth exposing directly to a program, because identical source code can run against interpreters with different capabilities.
A capability of the interpreter
The new variable does not simply report whether the operating system advertises a standard. The locale documentation at the release tag says native support includes Windows starting with Visual Studio 2005 and systems implementing the POSIX 2008 thread-safe locale operations. It also explains that some implementations are buggy enough for Perl build hints to disable their use.
An unthreaded interpreter reports 1. A threaded interpreter using thread-safe locale operations also reports 1. Builds that disable those operations report 0. That means the value answers whether this interpreter provides safe locale operation, with an unthreaded build as a separate reason for a positive answer. It is not a test for the presence of Perl threads.
Build configuration matters as well. The documentation supplies NO_THREAD_SAFE_LOCALE as a way to select the old implementation, and NO_POSIX_2008_LOCALE as a way to avoid the relevant POSIX facilities. These options can be necessary when system support is defective. A deployment cannot infer the capability solely from the host platform name when the interpreter itself can disable it.
That explicit flag helps a locale-dependent component state its requirements. A program that needs concurrent threads to change locales independently has a different requirement from a program that never changes locale after startup. The former depends on a facility that the documentation says is not portable to platforms lacking native thread-safe support. ${^SAFE_LOCALES} makes that dependency observable inside Perl.
New threads have a documented starting point
The initial program still starts with the locale selected through its environment. Newly created threads, however, start with LC_ALL set to "C". Each thread can query or change its locale with POSIX::setlocale() without changing another thread. Locale-dependent operations then use the locale belonging to that thread.
The distinction between the initial program and a newly created thread is material. A program cannot assume that a worker begins with the locale selected for the initial program merely because the worker was created there. The documentation gives the new worker a specific starting setting. Code that depends on another setting needs to establish it in that thread.
This arrangement also changes the meaning of a locale switch during concurrent execution. A switch can express the requirements of one worker without asking unrelated workers to accept the same setting. The benefit follows from the ownership of the setting, rather than from a new syntax for locale-dependent work. Perl code still uses the documented locale interfaces.
The release notes give a related numeric example. On threaded interpreters with a decimal radix character other than a dot, a race could occur when a thread needed the real radix character. This release fixes that case with a mutex on systems without thread-safe locales. On systems with thread-safe locales the notes say the problem does not arise. The release therefore contains both the new native-support path and a narrower repair for the older path.
Native extensions retain responsibilities
The locale documentation says applications written entirely in Perl should receive the new behaviour transparently, subject to its listed caveats. XS code has a different position. Native code or libraries that call the system setlocale function, except on Windows, will likely need changes for a multithreaded application. They can bypass the interpreter interface that maintains the intended relationship between threads and locale state.
The variable documentation makes a further distinction. An individual thread can choose the global locale through switch_to_global_locale, and ${^SAFE_LOCALES} currently remains 1 in such a thread. The flag reports an interpreter capability. It does not continuously prove that every extension and every thread is using that capability safely.
I consider that a useful limit to state plainly. A capability flag can help a module refuse an unsupported arrangement, but it cannot certify native code that changes the arrangement after the check. The documentation keeps those two questions separate and points extension authors towards the locale-aware XS interface.
Systems without querylocale have additional restrictions described in the same document. An embedded interpreter needs to start while the global locale is active, and Perl needs to know the platform locale categories. These details follow from the difficulty of discovering per-thread locale names through the available system interfaces. Perl 5.27.9 improves concurrent locale handling while documenting where embedding and extension code must cooperate with the interpreter.