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_soc.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_soc.c')
-rw-r--r-- | lib/libc/rpc/rpc_soc.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c index 5922063..2568d43 100644 --- a/lib/libc/rpc/rpc_soc.c +++ b/lib/libc/rpc/rpc_soc.c @@ -360,6 +360,14 @@ registerrpc(prognum, versnum, procnum, progname, inproc, outproc) */ static thread_key_t clnt_broadcast_key; static resultproc_t clnt_broadcast_result_main; +static once_t clnt_broadcast_once = ONCE_INITIALIZER; + +static void +clnt_broadcast_key_init(void) +{ + + thr_keycreate(&clnt_broadcast_key, free); +} /* * Need to translate the netbuf address into sockaddr_in address. @@ -402,12 +410,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) if (thr_main()) clnt_broadcast_result_main = eachresult; else { - if (clnt_broadcast_key == 0) { - mutex_lock(&tsd_lock); - if (clnt_broadcast_key == 0) - thr_keycreate(&clnt_broadcast_key, free); - mutex_unlock(&tsd_lock); - } + thr_once(&clnt_broadcast_once, clnt_broadcast_key_init); thr_setspecific(clnt_broadcast_key, (void *) eachresult); } return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers, |