Thread safety of getaddrinfo()/getnameinfo()

From: Felix Palmen <zirias_at_FreeBSD.org>
Date: Wed, 26 Apr 2023 17:57:43 UTC
Hi all,

if I'm not mistaken, POSIX says getaddrinfo() and getnameinfo() should
be thread-safe.

Consider this silly test code:

#v+
#include <netdb.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>

struct data {
    const char *hostname;
    struct addrinfo *res;
};

struct data threaddat[5] = {
    { "www.freebsd.org", 0 },
    { "www.google.com", 0 },
    { "www.freshports.org", 0 },
    { "www.github.com", 0 },
    { "www.kernel.org", 0 }
};

pthread_t threads[5];

void *resolve(void *d) {
    struct data *data = d;
    getaddrinfo(data->hostname, 0, 0, &data->res);
    return 0;
}

int main(void) {
    int i;
    for (i = 0; i < 5; ++i) {
        pthread_create(&threads[i], 0, resolve, &threaddat[i]);
    }
    for (i = 0; i < 5; ++i) {
        pthread_join(threads[i], 0);
        freeaddrinfo(threaddat[i].res);
    }
    return 0;
}
#v-

Running it through `valgrind --tool=helgrind` on 13.2-RELEASE produces
lots of these errors:

#v+
==60960== Possible data race during write of size 4 at 0x4A757E4 by thread #5
==60960== Locks held: none
==60960==    at 0x4993391: __h_errno_set (in /lib/libc.so.7)
==60960==    by 0x4968F9E: ??? (in /lib/libc.so.7)
==60960==    by 0x496854E: ??? (in /lib/libc.so.7)
==60960==    by 0x4978E1C: nsdispatch (in /lib/libc.so.7)
==60960==    by 0x496694C: ??? (in /lib/libc.so.7)
==60960==    by 0x49664EA: getaddrinfo (in /lib/libc.so.7)
==60960==    by 0x201A2E: resolve (resolvtest.c:23)
==60960==    by 0x485E066: ??? (in /usr/local/libexec/valgrind/vgpreload_helgrind-amd64-freebsd.so)
==60960==    by 0x4871A79: ??? (in /lib/libthr.so.3)
==60960== 
==60960== This conflicts with a previous write of size 4 by thread #6
==60960== Locks held: none
==60960==    at 0x4993391: __h_errno_set (in /lib/libc.so.7)
==60960==    by 0x496841F: ??? (in /lib/libc.so.7)
==60960==    by 0x4978E1C: nsdispatch (in /lib/libc.so.7)
==60960==    by 0x496694C: ??? (in /lib/libc.so.7)
==60960==    by 0x49664EA: getaddrinfo (in /lib/libc.so.7)
==60960==    by 0x201A2E: resolve (resolvtest.c:23)
==60960==    by 0x485E066: ??? (in /usr/local/libexec/valgrind/vgpreload_helgrind-amd64-freebsd.so)
==60960==    by 0x4871A79: ??? (in /lib/libthr.so.3)
==60960==  Address 0x4a757e4 is 0 bytes inside data symbol "h_errno"
#v-

So, is there a thread-safety issue with these functions, or a bug in
valgrind, or maybe just some false positive?

Thanks, Felix

-- 
 Felix Palmen <zirias@FreeBSD.org>     {private}   felix@palmen-it.de
 -- ports committer (mentee) --            {web}  http://palmen-it.de
 {pgp public key}  http://palmen-it.de/pub.txt
 {pgp fingerprint} 6936 13D5 5BBF 4837 B212  3ACC 54AD E006 9879 F231