diff options
author | delphij <delphij@FreeBSD.org> | 2009-06-24 23:17:16 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2009-06-24 23:17:16 +0000 |
commit | 5bc2a22774fc9b6542941c9fe7b6b1f68c717127 (patch) | |
tree | bbc4d05558e376fc0ae5440b555fce256925267b /lib/libc | |
parent | 8f1962d8fc528050e30fea347d88c0f96b905608 (diff) | |
download | FreeBSD-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/libc')
-rw-r--r-- | lib/libc/rpc/getnetconfig.c | 52 |
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) { |