[svn-commits] tilghman: trunk r910 - /trunk/res/res_config_mysql.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu May 14 14:16:58 CDT 2009


Author: tilghman
Date: Thu May 14 14:16:53 2009
New Revision: 910

URL: http://svn.asterisk.org/svn-view/asterisk-addons?view=rev&rev=910
Log:
Change database list to be rwlist locks, to avoid a potential deadlock between 2 readers.
(closes issue #15023, related to issue #15090)
 Reported by: cristiandimache
 Patches: 
       20090514__issue15090.diff.txt uploaded by tilghman (license 14)
 Tested by: cristiandimache

Modified:
    trunk/res/res_config_mysql.c

Modified: trunk/res/res_config_mysql.c
URL: http://svn.asterisk.org/svn-view/asterisk-addons/trunk/res/res_config_mysql.c?view=diff&rev=910&r1=909&r2=910
==============================================================================
--- trunk/res/res_config_mysql.c (original)
+++ trunk/res/res_config_mysql.c Thu May 14 14:16:53 2009
@@ -87,7 +87,7 @@
 enum requirements { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR };
 
 struct mysql_conn {
-	AST_LIST_ENTRY(mysql_conn) list;
+	AST_RWLIST_ENTRY(mysql_conn) list;
 	ast_mutex_t	lock;
 	MYSQL       handle;
 	char        host[50];
@@ -120,7 +120,7 @@
 };
 
 static AST_LIST_HEAD_STATIC(mysql_tables, tables);
-static AST_LIST_HEAD_STATIC(databases, mysql_conn);
+static AST_RWLIST_HEAD_STATIC(databases, mysql_conn);
 
 static int parse_config(int reload);
 static int mysql_reconnect(struct mysql_conn *conn);
@@ -154,14 +154,14 @@
 		whichdb = ast_strdupa(database);
 	}
 
-	AST_LIST_LOCK(&databases);
-	AST_LIST_TRAVERSE(&databases, cur, list) {
+	AST_RWLIST_RDLOCK(&databases);
+	AST_RWLIST_TRAVERSE(&databases, cur, list) {
 		if (!strcmp(cur->unique_name, whichdb)) {
 			ast_mutex_lock(&cur->lock);
 			break;
 		}
 	}
-	AST_LIST_UNLOCK(&databases);
+	AST_RWLIST_UNLOCK(&databases);
 	return cur;
 }
 
@@ -1393,12 +1393,13 @@
 	ast_module_user_hangup_all();
 
 	usleep(1);
-	AST_LIST_LOCK(&databases);
-	while ((cur = AST_LIST_REMOVE_HEAD(&databases, list))) {
+	AST_RWLIST_WRLOCK(&databases);
+	while ((cur = AST_RWLIST_REMOVE_HEAD(&databases, list))) {
 		mysql_close(&cur->handle);
 		ast_mutex_destroy(&cur->lock);
 		ast_free(cur);
 	}
+	AST_RWLIST_UNLOCK(&databases);
 
 	/* Destroy cached table info */
 	AST_LIST_LOCK(&mysql_tables);
@@ -1436,10 +1437,10 @@
 		ast_log(LOG_ERROR, "Not %sloading " RES_CONFIG_MYSQL_CONF "\n", reload ? "re" : "");
 	}
 
-	AST_LIST_LOCK(&databases);
+	AST_RWLIST_WRLOCK(&databases);
 	for (catg = ast_category_browse(config, NULL); catg; catg = ast_category_browse(config, catg)) {
 		/* Does this category already exist? */
-		AST_LIST_TRAVERSE(&databases, cur, list) {
+		AST_RWLIST_TRAVERSE(&databases, cur, list) {
 			if (!strcmp(cur->unique_name, catg)) {
 				break;
 			}
@@ -1453,12 +1454,12 @@
 
 			strcpy(cur->unique_name, catg); /* SAFE */
 			ast_mutex_init(&cur->lock);
-			AST_LIST_INSERT_TAIL(&databases, cur, list);
+			AST_RWLIST_INSERT_TAIL(&databases, cur, list);
 		}
 
 		load_mysql_config(config, catg, cur);
 	}
-	AST_LIST_UNLOCK(&databases);
+	AST_RWLIST_UNLOCK(&databases);
 
 	ast_config_destroy(config);
 
@@ -1628,14 +1629,14 @@
 			AST_LIST_UNLOCK(&mysql_tables);
 		} else {
 			struct mysql_conn *cur;
-			AST_LIST_LOCK(&databases);
-			AST_LIST_TRAVERSE(&databases, cur, list) {
+			AST_RWLIST_RDLOCK(&databases);
+			AST_RWLIST_TRAVERSE(&databases, cur, list) {
 				if (!strncasecmp(a->word, cur->unique_name, l) && ++which > a->n) {
 					ret = ast_strdup(cur->unique_name);
 					break;
 				}
 			}
-			AST_LIST_UNLOCK(&databases);
+			AST_RWLIST_UNLOCK(&databases);
 		}
 		return ret;
 	}
@@ -1695,14 +1696,14 @@
 		return NULL;
 	case CLI_GENERATE:
 		if (a->argc == 4) {
-			AST_LIST_LOCK(&databases);
-			AST_LIST_TRAVERSE(&databases, cur, list) {
+			AST_RWLIST_RDLOCK(&databases);
+			AST_RWLIST_TRAVERSE(&databases, cur, list) {
 				if (!strncasecmp(a->word, cur->unique_name, l) && ++which > a->n) {
 					ret = ast_strdup(cur->unique_name);
 					break;
 				}
 			}
-			AST_LIST_UNLOCK(&databases);
+			AST_RWLIST_UNLOCK(&databases);
 		}
 		return ret;
 	}
@@ -1710,8 +1711,8 @@
 	if (a->argc != 3)
 		return CLI_SHOWUSAGE;
 
-	AST_LIST_LOCK(&databases);
-	AST_LIST_TRAVERSE(&databases, cur, list) {
+	AST_RWLIST_RDLOCK(&databases);
+	AST_RWLIST_TRAVERSE(&databases, cur, list) {
 		if (a->argc == 3 || (a->argc == 4 && !strcasecmp(a->argv[3], cur->unique_name))) {
 			found = 1;
 
@@ -1752,7 +1753,7 @@
 			}
 		}
 	}
-	AST_LIST_UNLOCK(&databases);
+	AST_RWLIST_UNLOCK(&databases);
 
 	if (!found) {
 		ast_cli(a->fd, "No connections configured.\n");




More information about the svn-commits mailing list