Skip to content

Use getlocalename_l() if available - #24666

Draft
khwilliamson wants to merge 15 commits into
Perl:bleadfrom
khwilliamson:getlocalename_l
Draft

Use getlocalename_l() if available#24666
khwilliamson wants to merge 15 commits into
Perl:bleadfrom
khwilliamson:getlocalename_l

Conversation

@khwilliamson

Copy link
Copy Markdown
Contributor

This POSIX 2024 function solves long-standing thread unsafe behavior on platforms that properly implement it.

  • I'm unsure if this set of changes requires a perldelta entry

@tonycoz

tonycoz commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

The change looks reasonable, but I assume you see the cygwin failure.

As far as I can see cygwin is the only platform CI tests that has getlocalename_l().

@khwilliamson
khwilliamson marked this pull request as draft August 10, 2026 20:23
@khwilliamson

Copy link
Copy Markdown
Contributor Author

As with many of my PRs, if they go smoothly fine; if not, it'll have to wait until I get time to dig further. In this case, I will need to get a current cygwin set up for debugging.

Given that basically every OS we test on has some bug or another with locale handling, I'm more inclined to think this is their problem, and it just hasn't been tested sufficiently until we came along. But it's premature to make that assertion.

I've converted this to draft

It was recently placed in the wrong place in the list.
These are base level macros that need to be visible because they are
called by generally visible higher level macros, but shouldn't be used
by themselves; I think documenting them would encourage inappropriate
use of them.
Rather than having a 12 element list, just document pTHX_1, and mention
the others.  But have X<> elements for all of them, and make sure in
regen/embed.pl that they are all available to all code
@khwilliamson

Copy link
Copy Markdown
Contributor Author

I can't see how it could be anything other than a bug(s) in cygwin. It's dying in getlocalename_l() when called with category LC_ALL, and the object parameter has been set to the C locale. If instead I loop through the individual categories, it doesn't die and each properly returns C. That indicates it can't handle LC_ALL on this simple case.

I'm not convinced that is the only bug.

I presume they will want a non-Perl simple reproducer.

@tonycoz

tonycoz commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

https://cygwin.com/pipermail/cygwin/2026-August/259965.html

It's easy to make it crash:

tony@GANYMEDE ~/play
$ uname -a
CYGWIN_NT-10.0-19045 GANYMEDE 3.6.10-1.x86_64 2026-07-13 20:20 UTC x86_64 Cygwin

tony@GANYMEDE ~/play
$ cat getlcn_l.c
#include <locale.h>
#include <stdio.h>

int main(int argc, char **argv) {
  if (argc < 2) {
    fprintf(stderr, "Usage: %s locale-name\n");
    return 1;
  }
    
  locale_t lc = newlocale(LC_ALL_MASK, argv[1], 0);
  puts("newlocale");
  if (!lc) {
    perror("newlocale");
    return 1;
  }
  const char *name = getlocalename_l(LC_ALL, lc);
  printf("name '%s'\n", name);
}

tony@GANYMEDE ~/play
$ cc -ogetlcn_l.exe -g getlcn_l.c 

tony@GANYMEDE ~/play
$ ./getlcn_l C
newlocale

tony@GANYMEDE ~/play
$ ./getlcn_l en_AU.UTF-8
newlocale
name 'en_AU.UTF-8'

tony@GANYMEDE ~/play
$ gdb --args ./getlcn_l C
GNU gdb (GDB) (Cygwin 15.2-1) 15.2
Copyright (C) 2024 Free Software Foundation, Inc.
...
Reading symbols from ./getlcn_l...
(gdb) r
Starting program: /home/tony/play/getlcn_l C
[New Thread 7356.0x2d20]
[New Thread 7356.0x4f88]
[New Thread 7356.0x6684]
newlocale

Thread 1 "getlcn_l" received signal SIGTRAP, Trace/breakpoint trap.
0x00007ff88aba9823 in KERNELBASE!DebugBreak ()
   from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
(gdb) bt
#0  0x00007ff88aba9823 in KERNELBASE!DebugBreak ()
   from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
#1  0x00007ff8561264a7 in break_here ()
    at /usr/src/debug/cygwin-3.6.10-1/winsup/cygwin/dcrt0.cc:473
#2  0x00007ff8561403e2 in try_to_debug ()
    at /usr/src/debug/cygwin-3.6.10-1/winsup/cygwin/exceptions.cc:599
#3  exception::handle (e=0x7ffffc970, frame=<optimized out>, in=0x7ffffc480, 
    dispatch=<optimized out>)
    at /usr/src/debug/cygwin-3.6.10-1/winsup/cygwin/exceptions.cc:812
#4  0x00007ff88d2729df in ntdll!.chkstk ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#5  0x00007ff88d222554 in ntdll!RtlRaiseException ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#6  0x00007ff88d2714ee in ntdll!KiUserExceptionDispatcher ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#7  0x00007ff8562c70b4 in strcpy (dst0=0x0, src0=<optimized out>)
    at /usr/src/debug/cygwin-3.6.10-1/newlib/libc/string/strcpy.c:70
#8  0x00007ff8562d043f in __currentlocale (locobj=0x7ff8563e10c0 <__C_locale>, 
    locale_string=0x7ff8563e11a0 <__C_locale+224> "C")
    at /usr/src/debug/cygwin-3.6.10-1/newlib/libc/locale/locale.c:460
#9  0x00007ff856276cf4 in _sigfe () at sigfe.s:35
#10 0x0000000100401118 in main (argc=2, argv=0xa00002900) at getlcn_l.c:16

@tonycoz

tonycoz commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

sisyphus and others added 12 commits August 24, 2026 10:59
If nvtype is either double, DoubleDouble, or 80-bit extended precision long double, it checks the smallest possible positive value (aka DENORM_MIN).  Else, (IEEE 754 long double or __float128), it checks a subnormal that's larger than DENORM_MIN.  (It could easily be extended to cover DENORM_MIN for all nvtypes.)

Contributed by Sisyphus in GH Perl#9388.

Committer: arith2.t: Accommodate variable number of tests run

When compiled with -Dusequadmath, one more element is added to @v in the
'unless' block starting at line 72.  Hence, don't specify number of
tests exactly; allow flexibility.
When saving a pointer to the just-matched string and copying the string,
`S_reg_set_capture_string` has a COW branch and a non-COW branch. Some
common code follows the two branches:

```
        RXp_SUBCOFFSET(prog) = RXp_SUBOFFSET(prog);
        if (RXp_SUBOFFSET(prog) && utf8_target) {
            ....
        }
```

However, the COW branch concludes with:
```
            RXp_SUBOFFSET(prog) = 0;
            RXp_SUBCOFFSET(prog) = 0;
```

Since the common code cannot achieve anything in the COW case,
this commit moves it inside the non-COW branch.
The types Size_t and SSize_t were introduced in 5.000.

STRLEN was introduced in 3.0.
There weren't releases for the intermediate versions, so they aren't
dated.
This struct is visible to all code.  I noticed in grepping metacpan that
some modules use this spelling to refer to other things, so there is a
potential clash.  Since this is used only in generated code, it is easy
to rename it to use a spelling reserved for Perl's use.
PERL_EXT_RE_BUILD was listed twice.  Remove the one where it was
unconditionally set false; retaining the more flexible, hence accurate,
one.
I did some more grepping of the source to look for symbols that we can
assume are undefined for general usage, cpan and darkpan.  An example is
PERL_EXT_POSIX (seeing that in the source prompted this endeavor).  That
symbol should only be defined when compiling the POSIX module, so any
symbols created only while it is #defined, won't be visible to the
outside world.

I looked for "/ \b PERL_ \w+ /x" and scanned through the list.  The
result are the symbols added here, which showed that 5 symbols this
previously thought were visible everywhere actually aren't.  So they are
removed from the list.
This works on ASCII boxes, but not otherwise.  Instead use the macro
named and designed for the purpose
This POSIX 2024 function solves long-standing thread unsafe behavior on
platforms that properly implement it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants