[asterisk-commits] jrose: branch 1.8 r354263 - /branches/1.8/cdr/cdr_pgsql.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Feb 7 09:04:45 CST 2012


Author: jrose
Date: Tue Feb  7 09:04:38 2012
New Revision: 354263

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=354263
Log:
Fix column duplication bug in module reload for cdr_pgsql.

Prior to this patch, attempts to reload cdr_pgsql.so would cause the column list to keep
its current data and then add a second copy during the reload. This would cause attempts
to log the CDR to the database to fail. This patch also cleans up some unnecessary null
checks for ast_free and deals with a few potential locking problems.

(closes issue ASTERISK-19216)
Reported by: Jacek Konieczny
Review: https://reviewboard.asterisk.org/r/1711/

Modified:
    branches/1.8/cdr/cdr_pgsql.c

Modified: branches/1.8/cdr/cdr_pgsql.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/cdr/cdr_pgsql.c?view=diff&rev=354263&r1=354262&r2=354263
==============================================================================
--- branches/1.8/cdr/cdr_pgsql.c (original)
+++ branches/1.8/cdr/cdr_pgsql.c Tue Feb  7 09:04:38 2012
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2003 - 2006
+ * Copyright (C) 2003 - 2012
  *
  * Matthew D. Hardeman <mhardemn at papersoft.com>
  * Adapted from the MySQL CDR logger originally by James Sharp
@@ -81,6 +81,7 @@
 						ast_free(sql);                                    \
 						ast_free(sql2);                                   \
 						AST_RWLIST_UNLOCK(&psql_columns);                 \
+						ast_mutex_unlock(&pgsql_lock);                    \
 						return -1;                                        \
 					}                                                     \
 				}                                                         \
@@ -94,6 +95,7 @@
 						ast_free(sql);                    \
 						ast_free(sql2);                   \
 						AST_RWLIST_UNLOCK(&psql_columns); \
+						ast_mutex_unlock(&pgsql_lock);    \
 						return -1;                        \
 					}                                     \
 				}                                         \
@@ -132,14 +134,10 @@
 		struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
 		char buf[257], escapebuf[513], *value;
 		int first = 1;
-  
+
 		if (!sql || !sql2) {
-			if (sql) {
-				ast_free(sql);
-			}
-			if (sql2) {
-				ast_free(sql2);
-			}
+			ast_free(sql);
+			ast_free(sql2);
 			return -1;
 		}
 
@@ -270,9 +268,10 @@
 				}
 			}
 			first = 0;
-  		}
+		}
+
+		LENGTHEN_BUF1(ast_str_strlen(sql2) + 2);
 		AST_RWLIST_UNLOCK(&psql_columns);
-		LENGTHEN_BUF1(ast_str_strlen(sql2) + 2);
 		ast_str_append(&sql, 0, ")%s)", ast_str_buffer(sql2));
 		ast_verb(11, "[%s]\n", ast_str_buffer(sql));
 
@@ -334,44 +333,34 @@
 	return 0;
 }
 
-static int unload_module(void)
+/* This function should be called without holding the pgsql_columns lock */
+static void empty_columns(void)
 {
 	struct columns *current;
-
-	ast_cdr_unregister(name);
-
-	PQfinish(conn);
-
-	if (pghostname) {
-		ast_free(pghostname);
-	}
-	if (pgdbname) {
-		ast_free(pgdbname);
-	}
-	if (pgdbuser) {
-		ast_free(pgdbuser);
-	}
-	if (pgpassword) {
-		ast_free(pgpassword);
-	}
-	if (pgdbport) {
-		ast_free(pgdbport);
-	}
-	if (table) {
-		ast_free(table);
-	}
-	if (encoding) {
-		ast_free(encoding);
-	}
-	if (tz) {
-		ast_free(tz);
-	}
-
 	AST_RWLIST_WRLOCK(&psql_columns);
 	while ((current = AST_RWLIST_REMOVE_HEAD(&psql_columns, list))) {
 		ast_free(current);
 	}
 	AST_RWLIST_UNLOCK(&psql_columns);
+
+}
+
+static int unload_module(void)
+{
+	ast_cdr_unregister(name);
+
+	PQfinish(conn);
+
+	ast_free(pghostname);
+	ast_free(pgdbname);
+	ast_free(pgdbuser);
+	ast_free(pgpassword);
+	ast_free(pgdbport);
+	ast_free(table);
+	ast_free(encoding);
+	ast_free(tz);
+
+	empty_columns();
 
 	return 0;
 }
@@ -389,12 +378,18 @@
 	if ((cfg = ast_config_load(config, config_flags)) == NULL || cfg == CONFIG_STATUS_FILEINVALID) {
 		ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
 		return -1;
-	} else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+	} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
 		return 0;
+	}
+
+	ast_mutex_lock(&pgsql_lock);
 
 	if (!(var = ast_variable_browse(cfg, "global"))) {
 		ast_config_destroy(cfg);
-		return 0;
+		ast_mutex_unlock(&pgsql_lock);
+		ast_log(LOG_NOTICE, "cdr_pgsql configuration contains no global section, skipping module %s.\n",
+			reload ? "reload" : "load");
+		return -1;
 	}
 
 	if (!(tmp = ast_variable_retrieve(cfg, "global", "hostname"))) {
@@ -402,10 +397,10 @@
 		tmp = "";	/* connect via UNIX-socket by default */
 	}
 
-	if (pghostname)
-		ast_free(pghostname);
+	ast_free(pghostname);
 	if (!(pghostname = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -414,10 +409,10 @@
 		tmp = "asteriskcdrdb";
 	}
 
-	if (pgdbname)
-		ast_free(pgdbname);
+	ast_free(pgdbname);
 	if (!(pgdbname = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -426,10 +421,10 @@
 		tmp = "asterisk";
 	}
 
-	if (pgdbuser)
-		ast_free(pgdbuser);
+	ast_free(pgdbuser);
 	if (!(pgdbuser = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -438,10 +433,10 @@
 		tmp = "";
 	}
 
-	if (pgpassword)
-		ast_free(pgpassword);
+	ast_free(pgpassword);
 	if (!(pgpassword = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -450,10 +445,10 @@
 		tmp = "5432";
 	}
 
-	if (pgdbport)
-		ast_free(pgdbport);
+	ast_free(pgdbport);
 	if (!(pgdbport = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -462,10 +457,10 @@
 		tmp = "cdr";
 	}
 
-	if (table)
-		ast_free(table);
+	ast_free(table);
 	if (!(table = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -474,11 +469,10 @@
 		tmp = "LATIN9";
 	}
 
-	if (encoding) {
-		ast_free(encoding);
-	}
+	ast_free(encoding);
 	if (!(encoding = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -486,12 +480,12 @@
 		tmp = "";
 	}
 
-	if (tz) {
-		ast_free(tz);
-		tz = NULL;
-	}
+	ast_free(tz);
+	tz = NULL;
+
 	if (!ast_strlen_zero(tmp) && !(tz = ast_strdup(tmp))) {
 		ast_config_destroy(cfg);
+		ast_mutex_unlock(&pgsql_lock);
 		return -1;
 	}
 
@@ -577,6 +571,7 @@
 			ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror);
 			PQclear(result);
 			unload_module();
+			ast_mutex_unlock(&pgsql_lock);
 			return AST_MODULE_LOAD_DECLINE;
 		}
 
@@ -585,8 +580,12 @@
 			ast_log(LOG_ERROR, "cdr_pgsql: Failed to query database columns. No columns found, does the table exist?\n");
 			PQclear(result);
 			unload_module();
+			ast_mutex_unlock(&pgsql_lock);
 			return AST_MODULE_LOAD_DECLINE;
 		}
+
+		/* Clear out the columns list. */
+		empty_columns();
 
 		for (i = 0; i < rows; i++) {
 			fname = PQgetvalue(result, i, 0);
@@ -616,7 +615,9 @@
 				} else {
 					cur->hasdefault = 0;
 				}
+				AST_RWLIST_WRLOCK(&psql_columns);
 				AST_RWLIST_INSERT_TAIL(&psql_columns, cur, list);
+				AST_RWLIST_UNLOCK(&psql_columns);
 			}
 		}
 		PQclear(result);
@@ -629,12 +630,17 @@
 
 	ast_config_destroy(cfg);
 
-	return ast_cdr_register(name, ast_module_info->description, pgsql_log);
+	ast_mutex_unlock(&pgsql_lock);
+	return 0;
 }
 
 static int load_module(void)
 {
-	return config_module(0) ? AST_MODULE_LOAD_DECLINE : 0;
+	if (config_module(0)) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	return ast_cdr_register(name, ast_module_info->description, pgsql_log)
+		? AST_MODULE_LOAD_DECLINE : 0;
 }
 
 static int reload(void)




More information about the asterisk-commits mailing list