From eccfeaf9b47b86d9440bd79f16d790ca050dbaba Mon Sep 17 00:00:00 2001
From: Russell Bryant <russell@russellbryant.com>
Date: Sun, 21 Jun 2009 16:11:48 +0000
Subject: [PATCH] Fix possibility of crashiness during reload in custom fields
 handling.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@202262 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 cdr/cdr_manager.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/cdr/cdr_manager.c b/cdr/cdr_manager.c
index 82f8a6e17c..83e6054dd6 100644
--- a/cdr/cdr_manager.c
+++ b/cdr/cdr_manager.c
@@ -47,11 +47,8 @@ static char *name = "cdr_manager";
 
 static int enablecdr = 0;
 
-/*! 
- * XXX
- * \bug The handling of this variable is not thread-safe.  Crashes are possible on reload.
- */
 static struct ast_str *customfields;
+AST_RWLOCK_DEFINE_STATIC(customfields_lock);
 
 static int manager_log(struct ast_cdr *cdr);
 
@@ -73,11 +70,6 @@ static int load_config(int reload)
 		return -1;
 	}
 
-	if (reload && customfields) {
-		ast_free(customfields);
-	}
-	customfields = NULL;
-
 	if (!cfg) {
 		/* Standard configuration */
 		ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
@@ -87,6 +79,15 @@ static int load_config(int reload)
 		return -1;
 	}
 
+	if (reload) {
+		ast_rwlock_wrlock(&customfields_lock);
+	}
+
+	if (reload && customfields) {
+		ast_free(customfields);
+		customfields = NULL;
+	}
+
 	while ( (cat = ast_category_browse(cfg, cat)) ) {
 		if (!strcasecmp(cat, "general")) {
 			v = ast_variable_browse(cfg, cat);
@@ -115,6 +116,10 @@ static int load_config(int reload)
 		}
 	}
 
+	if (reload) {
+		ast_rwlock_unlock(&customfields_lock);
+	}
+
 	ast_config_destroy(cfg);
 
 	if (enablecdr && !newenablecdr)
@@ -148,9 +153,9 @@ static int manager_log(struct ast_cdr *cdr)
 	ast_localtime(&cdr->end, &timeresult, NULL);
 	ast_strftime(strEndTime, sizeof(strEndTime), DATE_FORMAT, &timeresult);
 
-	buf[0] = 0;
-	/* Custom fields handling */
-	if (customfields != NULL && ast_str_strlen(customfields)) {
+	buf[0] = '\0';
+	ast_rwlock_rdlock(&customfields_lock);
+	if (customfields && ast_str_strlen(customfields)) {
 		struct ast_channel *dummy = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Substitution/%p", cdr);
 		if (!dummy) {
 			ast_log(LOG_ERROR, "Unable to allocate channel for variable substitution.\n");
@@ -160,6 +165,7 @@ static int manager_log(struct ast_cdr *cdr)
 		pbx_substitute_variables_helper(dummy, ast_str_buffer(customfields), buf, sizeof(buf) - 1);
 		ast_channel_release(dummy);
 	}
+	ast_rwlock_unlock(&customfields_lock);
 
 	manager_event(EVENT_FLAG_CDR, "Cdr",
 	    "AccountCode: %s\r\n"
-- 
GitLab