[asterisk-commits] jrose: trunk r354275 - in /trunk: ./ cdr/cdr_pgsql.c

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


Author: jrose
Date: Tue Feb  7 09:29:14 2012
New Revision: 354275

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=354275
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/
........

Merged revisions 354263 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 354270 from http://svn.asterisk.org/svn/asterisk/branches/10

Modified:
    trunk/   (props changed)
    trunk/cdr/cdr_pgsql.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-10-merged' - no diff available.

Modified: trunk/cdr/cdr_pgsql.c
URL: http://svnview.digium.com/svn/asterisk/trunk/cdr/cdr_pgsql.c?view=diff&rev=354275&r1=354274&r2=354275
==============================================================================
--- trunk/cdr/cdr_pgsql.c (original)
+++ trunk/cdr/cdr_pgsql.c Tue Feb  7 09:29:14 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
@@ -90,6 +90,7 @@
 						ast_free(sql);                                    \
 						ast_free(sql2);                                   \
 						AST_RWLIST_UNLOCK(&psql_columns);                 \
+						ast_mutex_unlock(&pgsql_lock);                    \
 						return -1;                                        \
 					}                                                     \
 				}                                                         \
@@ -103,6 +104,7 @@
 						ast_free(sql);                    \
 						ast_free(sql2);                   \
 						AST_RWLIST_UNLOCK(&psql_columns); \
+						ast_mutex_unlock(&pgsql_lock);    \
 						return -1;                        \
 					}                                     \
 				}                                         \
@@ -198,14 +200,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;
 		}
 
@@ -336,9 +334,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));
 
@@ -414,45 +413,35 @@
 	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);
-	ast_cli_unregister_multiple(cdr_pgsql_status_cli, ARRAY_LEN(cdr_pgsql_status_cli));
-
-	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);
+	ast_cli_unregister_multiple(cdr_pgsql_status_cli, ARRAY_LEN(cdr_pgsql_status_cli));
+
+	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;
 }
@@ -474,9 +463,14 @@
 		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"))) {
@@ -484,11 +478,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;
 	}
 
@@ -497,11 +490,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;
 	}
 
@@ -510,11 +502,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;
 	}
 
@@ -523,11 +514,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;
 	}
 
@@ -536,11 +526,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;
 	}
 
@@ -549,11 +538,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;
 	}
 
@@ -562,11 +550,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;
 	}
 
@@ -574,12 +561,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;
 	}
 
@@ -667,6 +654,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;
 		}
 
@@ -675,8 +663,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);
@@ -706,7 +698,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);
@@ -719,13 +713,18 @@
 
 	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)
 {
 	ast_cli_register_multiple(cdr_pgsql_status_cli, sizeof(cdr_pgsql_status_cli) / sizeof(struct ast_cli_entry));
-	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