summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2009-06-24 23:17:16 +0000
committerdelphij <delphij@FreeBSD.org>2009-06-24 23:17:16 +0000
commit5bc2a22774fc9b6542941c9fe7b6b1f68c717127 (patch)
treebbc4d05558e376fc0ae5440b555fce256925267b /lib
parent8f1962d8fc528050e30fea347d88c0f96b905608 (diff)
downloadFreeBSD-src-5bc2a22774fc9b6542941c9fe7b6b1f68c717127.zip
FreeBSD-src-5bc2a22774fc9b6542941c9fe7b6b1f68c717127.tar.gz
Lock around access to nc_file and netconfig_info ("ni"). The RPC
part of libc is still not thread safe but this would at least reduce the problems we have. PR: threads/118544 Submitted by: Changming Sun <snnn119 gmail com> MFC after: 2 weeks
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/rpc/getnetconfig.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c
index 773650c..9baa224 100644
--- a/lib/libc/rpc/getnetconfig.c
+++ b/lib/libc/rpc/getnetconfig.c
@@ -130,7 +130,11 @@ 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 struct netconfig_info ni = { 0, 0, NULL, NULL};
+static pthread_mutex_t ni_lock = PTHREAD_MUTEX_INITIALIZER;
+
#define MAXNETCONFIGLINE 1000
@@ -204,14 +208,24 @@ setnetconfig()
* For multiple calls, i.e. nc_file is not NULL, we just return the
* handle without reopening the netconfig db.
*/
+ mutex_lock(&ni_lock);
ni.ref++;
+ mutex_unlock(&ni_lock);
+
+ mutex_lock(&nc_file_lock);
if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
nc_vars->valid = NC_VALID;
nc_vars->flag = 0;
nc_vars->nc_configs = ni.head;
+ mutex_unlock(&nc_file_lock);
return ((void *)nc_vars);
}
+ mutex_unlock(&nc_file_lock);
+
+ mutex_lock(&ni_lock);
ni.ref--;
+ mutex_unlock(&ni_lock);
+
nc_error = NC_NONETCONFIG;
free(nc_vars);
return (NULL);
@@ -234,14 +248,18 @@ void *handlep;
char *stringp; /* tmp string pointer */
struct netconfig_list *list;
struct netconfig *np;
+ struct netconfig *result;
/*
* Verify that handle is valid
*/
+ mutex_lock(&nc_file_lock);
if (ncp == NULL || nc_file == NULL) {
nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_file_lock);
return (NULL);
}
+ mutex_unlock(&nc_file_lock);
switch (ncp->valid) {
case NC_VALID:
@@ -255,7 +273,9 @@ void *handlep;
*/
if (ncp->flag == 0) { /* first time */
ncp->flag = 1;
+ mutex_lock(&ni_lock);
ncp->nc_configs = ni.head;
+ mutex_unlock(&ni_lock);
if (ncp->nc_configs != NULL) /* entry already exist */
return(ncp->nc_configs->ncp);
}
@@ -268,7 +288,13 @@ void *handlep;
* If we cannot find the entry in the list and is end of file,
* we give up.
*/
- if (ni.eof == 1) return(NULL);
+ mutex_lock(&ni_lock);
+ if (ni.eof == 1) {
+ mutex_unlock(&ni_lock);
+ return(NULL);
+ }
+ mutex_unlock(&ni_lock);
+
break;
default:
nc_error = NC_NOTINIT;
@@ -289,13 +315,18 @@ void *handlep;
/*
* Read a line from netconfig file.
*/
+ mutex_lock(&nc_file_lock);
do {
if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
free(stringp);
+ mutex_lock(&ni_lock);
ni.eof = 1;
+ mutex_unlock(&ni_lock);
+ mutex_unlock(&nc_file_lock);
return (NULL);
}
} while (*stringp == '#');
+ mutex_unlock(&nc_file_lock);
list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
if (list == NULL) {
@@ -325,6 +356,7 @@ void *handlep;
* Reposition the current pointer of the handle to the last entry
* in the list.
*/
+ mutex_lock(&ni_lock);
if (ni.head == NULL) { /* first entry */
ni.head = ni.tail = list;
}
@@ -333,7 +365,9 @@ void *handlep;
ni.tail = ni.tail->next;
}
ncp->nc_configs = ni.tail;
- return(ni.tail->ncp);
+ result = ni.tail->ncp;
+ mutex_unlock(&ni_lock);
+ return(result);
}
}
@@ -367,7 +401,9 @@ void *handlep;
nc_handlep->valid = NC_INVALID;
nc_handlep->flag = 0;
nc_handlep->nc_configs = NULL;
+ mutex_lock(&ni_lock);
if (--ni.ref > 0) {
+ mutex_unlock(&ni_lock);
free(nc_handlep);
return(0);
}
@@ -380,6 +416,8 @@ void *handlep;
ni.eof = ni.ref = 0;
ni.head = NULL;
ni.tail = NULL;
+ mutex_unlock(&ni_lock);
+
while (q) {
p = q->next;
if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
@@ -390,8 +428,11 @@ void *handlep;
}
free(nc_handlep);
+ mutex_lock(&nc_file_lock);
fclose(nc_file);
nc_file = NULL;
+ mutex_unlock(&nc_file_lock);
+
return (0);
}
@@ -427,15 +468,20 @@ getnetconfigent(netid)
* If all the netconfig db has been read and placed into the list and
* there is no match for the netid, return NULL.
*/
+ mutex_lock(&ni_lock);
if (ni.head != NULL) {
for (list = ni.head; list; list = list->next) {
if (strcmp(list->ncp->nc_netid, netid) == 0) {
+ mutex_unlock(&ni_lock);
return(dup_ncp(list->ncp));
}
}
- if (ni.eof == 1) /* that's all the entries */
+ if (ni.eof == 1) { /* that's all the entries */
+ mutex_unlock(&ni_lock);
return(NULL);
+ }
}
+ mutex_unlock(&ni_lock);
if ((file = fopen(NETCONFIG, "r")) == NULL) {
OpenPOWER on IntegriCloud