This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
locale.c: strerror_l() not fool proof
authorKarl Williamson <khw@cpan.org>
Tue, 12 Sep 2017 00:57:54 +0000 (18:57 -0600)
committerKarl Williamson <khw@cpan.org>
Fri, 10 Nov 2017 01:51:59 +0000 (18:51 -0700)
commit43cb665150ddf892c277cba7edc80937fa053fb1
treed140ff7a2ff7a4a9d6363744ff6bb2455cd85996
parent63e5b0d74e16f32c89cdb039e79f0fdb47d1b819
locale.c: strerror_l() not fool proof

Commit 7aaa36b196e5a478a3d1bd32506797db7cebf0b2 changed to use
strerror_l() if available on the platform.  But there is a potential bug
with this on threaded perls.  The code uses strerror_l() when it needs
the answer on a locale that isn't necessarily the current one.  But it
uses plain strerror() when the locale is known to be the current one.
Plain strerror() isn't necessarily thread-safe.  However, on systems
that have strerror_r(), reentr.h has caused our apparent call to plain
strerror() to instead call the thread-safe strerror_r() under the hood.
So there is no bug on unthreaded perls nor on ones that have
strerror_r().

This commit fixes the bug on threaded builds which have strerror_l() but
not strerror_r().  It does this by using strerror_l() for everything,
and constructing a locale object that is the current locale to use when
the locale doesn't need to be changed.  This is somewhat more work than
the alternative above does, so that one is used if available.

No changes are made to how it works on systems that don't have
strerror_l().

Some systems have deprecated strerror_r().  reentr.h does not use it on
such systems.  The reason for the deprecation, we would hope, may be
that the plain strerror() is implemented thread-safely.  We don't know
that, so we just assume that the plain version is thread-unsafe.

We do have tests that try to find races here, but they haven't shown
any.  It could be that systems that are advanced enough to have
strerror_l() also have strerror_r().
locale.c