summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/clnt_simple.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/clnt_simple.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/clnt_simple.c')
-rw-r--r--lib/libc/rpc/clnt_simple.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c
index 12b6679..ba21d2d 100644
--- a/lib/libc/rpc/clnt_simple.c
+++ b/lib/libc/rpc/clnt_simple.c
@@ -76,7 +76,11 @@ struct rpc_call_private {
char nettype[NETIDLEN]; /* Network type */
};
static struct rpc_call_private *rpc_call_private_main;
+static thread_key_t rpc_call_key;
+static once_t rpc_call_once = ONCE_INITIALIZER;
+static int rpc_call_key_error;
+static void rpc_call_key_init(void);
static void rpc_call_destroy(void *);
static void
@@ -91,6 +95,13 @@ rpc_call_destroy(void *vp)
}
}
+static void
+rpc_call_key_init(void)
+{
+
+ rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy);
+}
+
/*
* This is the simplified interface to the client rpc layer.
* The client handle is not destroyed here and is reused for
@@ -112,17 +123,16 @@ rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
enum clnt_stat clnt_stat;
struct timeval timeout, tottimeout;
- static thread_key_t rpc_call_key;
int main_thread = 1;
if ((main_thread = thr_main())) {
rcp = rpc_call_private_main;
} else {
- if (rpc_call_key == 0) {
- mutex_lock(&tsd_lock);
- if (rpc_call_key == 0)
- thr_keycreate(&rpc_call_key, rpc_call_destroy);
- mutex_unlock(&tsd_lock);
+ if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 ||
+ rpc_call_key_error != 0) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = rpc_call_key_error;
+ return (rpc_createerr.cf_stat);
}
rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
}
OpenPOWER on IntegriCloud