summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/rpc_generic.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2010-03-10 13:23:25 +0000
committerjhb <jhb@FreeBSD.org>2010-03-10 13:23:25 +0000
commite0724fd324c89b8c46185fe402fd332141ea5bf5 (patch)
treedae7801acd654dfe736481930016ad68270d7757 /lib/libc/rpc/rpc_generic.c
parent42dc39ae95f85b0f1bedbdfa406342f9ac3e4fcc (diff)
downloadFreeBSD-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.c27
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) {
OpenPOWER on IntegriCloud