.`Socket::inet_aton()` can now be used from multiple threads safely
Previously, the `Socket::inet_aton()` function, used for resolving a domain name from multiple Perl threads, called the unsafe `gethostbyname()` `glibc` function. Consequently, an incorrect IPv4 address was occasionally returned, or the Perl interpreter terminated unexpectedly. With this update, the `Socket::inet_aton()` implementation has been changed to use the thread-safe `getaddrinfo()` `glibc` function instead of `gethostbyname()`. As a result, the `inet_aton()` function from Perl `Socket` module can be used from multiple threads safely.
+++ This bug was initially created as a clone of Bug #1693293 +++
It seems inet_aton should be thread safe (see https://stackoverflow.com/questions/2319469/is-perls-inet-aton-thread-safe) so there might be a bug with RHEL7's Perl.
[...]
and indeed, adding breakpoints to gethostbyname and gethostbyname_r it shows
gethostbyname is called from a thread; should call only gethostbyname_r.
Breakpoint 1, 0x00007ffff68096a0 in gethostbyname () from /lib64/libc.so.6
(gdb) bt
#0 0x00007ffff68096a0 in gethostbyname () from /lib64/libc.so.6
#1 0x00007fffef7a2363 in XS_Socket_inet_aton () from /usr/lib64/perl5/vendor_perl/auto/Socket/Socket.so
#2 0x00007ffff7b093ef in Perl_pp_entersub () from /usr/lib64/perl5/CORE/libperl.so
#3 0x00007ffff7b01b66 in Perl_runops_standard () from /usr/lib64/perl5/CORE/libperl.so
#4 0x00007ffff7a99148 in Perl_call_sv () from /usr/lib64/perl5/CORE/libperl.so
#5 0x00007fffefdbdcf9 in S_ithread_run () from /usr/lib64/perl5/vendor_perl/auto/threads/threads.so
#6 0x00007ffff6ac5dd5 in start_thread () from /lib64/libpthread.so.0
#7 0x00007ffff67eeead in clone () from /lib64/libc.so.6
[...]
--- Additional comment from Petr Pisar on 2019-03-27 16:22:18 GMT ---
Thank you for the report. I confirm I can reproduce the issue.
The inet_aton() function is provided by Socket Perl module and it indeed calls gethostbyname() that is not thread-safe:
void
inet_aton(host)
char * host
CODE:
{
struct in_addr ip_address;
struct hostent * phe;
if ((*host != '\0') && inet_aton(host, &ip_address)) {
ST(0) = sv_2mortal(newSVpvn((char *)&ip_address, sizeof(ip_address)));
XSRETURN(1);
}
→ phe = gethostbyname(host);
if (phe && phe->h_addrtype == AF_INET && phe->h_length == 4) {
ST(0) = sv_2mortal(newSVpvn((char *)phe->h_addr, phe->h_length));
XSRETURN(1);
}
XSRETURN_UNDEF;
}
As a workaround I recommend using getaddrinfo() from the same Socket module instead. It's thread safe and supports IPv6. As replacement for IO:Socket::INET I recommend IO::Socket::IP instead.
------
RHEL-8 is affected (perl-Socket-2.027-2.el8, perl-Socket-2.027-3.module+el8.1.0+2926+ce7246ad).
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.
For information on the advisory, and where to find the updated
files, follow the link below.
If the solution does not work for you, open a new bug report.
https://access.redhat.com/errata/RHBA-2019:3546