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/getnetconfig.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/getnetconfig.c')
-rw-r--r-- | lib/libc/rpc/getnetconfig.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c index e5db51a..1310e36 100644 --- a/lib/libc/rpc/getnetconfig.c +++ b/lib/libc/rpc/getnetconfig.c @@ -130,21 +130,29 @@ static struct netconfig *dup_ncp(struct netconfig *); static FILE *nc_file; /* for netconfig db */ -static pthread_mutex_t nc_file_lock = PTHREAD_MUTEX_INITIALIZER; +static mutex_t nc_file_lock = MUTEX_INITIALIZER; static struct netconfig_info ni = { 0, 0, NULL, NULL}; -static pthread_mutex_t ni_lock = PTHREAD_MUTEX_INITIALIZER; +static mutex_t ni_lock = MUTEX_INITIALIZER; +static thread_key_t nc_key; +static once_t nc_once = ONCE_INITIALIZER; +static int nc_key_error; + +static void +nc_key_init(void) +{ + + nc_key_error = thr_keycreate(&nc_key, free); +} #define MAXNETCONFIGLINE 1000 static int * __nc_error() { - static pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER; - static thread_key_t nc_key = 0; static int nc_error = 0; - int error, *nc_addr; + int *nc_addr; /* * Use the static `nc_error' if we are the main thread @@ -153,15 +161,8 @@ __nc_error() */ if (thr_main()) return (&nc_error); - if (nc_key == 0) { - error = 0; - mutex_lock(&nc_lock); - if (nc_key == 0) - error = thr_keycreate(&nc_key, free); - mutex_unlock(&nc_lock); - if (error) - return (&nc_error); - } + if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0) + return (&nc_error); if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { nc_addr = (int *)malloc(sizeof (int)); if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { |