svn commit: r195432 - in stable/6/lib/libc: . rpc

Xin LI delphij at FreeBSD.org
Wed Jul 8 01:43:48 UTC 2009


Author: delphij
Date: Wed Jul  8 01:43:47 2009
New Revision: 195432
URL: http://svn.freebsd.org/changeset/base/195432

Log:
  MFC r194932
  
  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>

Modified:
  stable/6/lib/libc/   (props changed)
  stable/6/lib/libc/rpc/getnetconfig.c

Modified: stable/6/lib/libc/rpc/getnetconfig.c
==============================================================================
--- stable/6/lib/libc/rpc/getnetconfig.c	Wed Jul  8 01:41:41 2009	(r195431)
+++ stable/6/lib/libc/rpc/getnetconfig.c	Wed Jul  8 01:43:47 2009	(r195432)
@@ -130,7 +130,11 @@ static struct netconfig *dup_ncp(struct 
 
 
 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);
 }
 
@@ -439,15 +480,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) {


More information about the svn-src-stable-6 mailing list