diff options
author | jhb <jhb@FreeBSD.org> | 2010-03-10 13:23:25 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2010-03-10 13:23:25 +0000 |
commit | e0724fd324c89b8c46185fe402fd332141ea5bf5 (patch) | |
tree | dae7801acd654dfe736481930016ad68270d7757 /lib/libc/rpc/rpc_generic.c | |
parent | 42dc39ae95f85b0f1bedbdfa406342f9ac3e4fcc (diff) | |
download | FreeBSD-src-e0724fd324c89b8c46185fe402fd332141ea5bf5.zip FreeBSD-src-e0724fd324c89b8c46185fe402fd332141ea5bf5.tar.gz |
Use thr_once() with once_t controls to initialize various thread_key_t
objects used to provide per-thread storage in the RPC code. Almost all
of these used double-checking with a dedicated mutex (tsd_lock) to do this
before. However, that is not always safe with more relaxed memory orders.
There were also other bugs, such as one in __rpc_createrr() that caused a
new key to be allocated each time __rpc_createrr() was invoked.
PR: threads/144558
Reported by: Sam Robb samrobb of averesystems com (key leak)
MFC after: 1 week
Diffstat (limited to 'lib/libc/rpc/rpc_generic.c')
-rw-r--r-- | lib/libc/rpc/rpc_generic.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c index 81bd92b..1bd7e15 100644 --- a/lib/libc/rpc/rpc_generic.c +++ b/lib/libc/rpc/rpc_generic.c @@ -221,6 +221,18 @@ getnettype(nettype) return (_rpctypelist[i].type); } +static thread_key_t tcp_key, udp_key; +static once_t keys_once = ONCE_INITIALIZER; +static int tcp_key_error, udp_key_error; + +static void +keys_init(void) +{ + + tcp_key_error = thr_keycreate(&tcp_key, free); + udp_key_error = thr_keycreate(&udp_key, free); +} + /* * For the given nettype (tcp or udp only), return the first structure found. * This should be freed by calling freenetconfigent() @@ -242,19 +254,10 @@ __rpc_getconfip(nettype) netid_udp = netid_udp_main; netid_tcp = netid_tcp_main; } else { - if (tcp_key == 0) { - mutex_lock(&tsd_lock); - if (tcp_key == 0) - thr_keycreate(&tcp_key, free); - mutex_unlock(&tsd_lock); - } + if (thr_once(&keys_once, keys_init) != 0 || + tcp_key_error != 0 || udp_key_error != 0) + return (NULL); netid_tcp = (char *)thr_getspecific(tcp_key); - if (udp_key == 0) { - mutex_lock(&tsd_lock); - if (udp_key == 0) - thr_keycreate(&udp_key, free); - mutex_unlock(&tsd_lock); - } netid_udp = (char *)thr_getspecific(udp_key); } if (!netid_udp && !netid_tcp) { |