[asterisk-commits] qwell: branch 1.4 r82344 - /branches/1.4/cdr/cdr_csv.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Sep 13 15:11:40 CDT 2007


Author: qwell
Date: Thu Sep 13 15:11:40 2007
New Revision: 82344

URL: http://svn.digium.com/view/asterisk?view=rev&rev=82344
Log:
Fix a crash that could occur in cdr_csv when mutliple threads tried to close the same file.

Do we actually need the locking here?  What happens if you open the same file twice, and
 two threads try to write to it at the same time?  Is fputs() going to write out the entire
 line at once?  I suspect that it could be possible for the second fopen to run during the
 first fputs, so the position could be in the middle of the previously written line...

Issue 10347, initial patch by explidous (but I removed all of the paranoia stuff..)

Modified:
    branches/1.4/cdr/cdr_csv.c

Modified: branches/1.4/cdr/cdr_csv.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/cdr/cdr_csv.c?view=diff&rev=82344&r1=82343&r2=82344
==============================================================================
--- branches/1.4/cdr/cdr_csv.c (original)
+++ branches/1.4/cdr/cdr_csv.c Thu Sep 13 15:11:40 2007
@@ -47,6 +47,7 @@
 #include "asterisk/module.h"
 #include "asterisk/logger.h"
 #include "asterisk/utils.h"
+#include "asterisk/lock.h"
 
 #define CSV_LOG_DIR "/cdr-csv"
 #define CSV_MASTER  "/Master.csv"
@@ -91,8 +92,8 @@
 
 static char *name = "csv";
 
-static FILE *mf = NULL;
-
+AST_MUTEX_DEFINE_STATIC(mf_lock);
+AST_MUTEX_DEFINE_STATIC(acf_lock);
 
 static int load_config(void)
 {
@@ -266,18 +267,26 @@
 		return -1;
 	}
 	snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
+
+	ast_mutex_lock(&acf_lock);
 	f = fopen(tmp, "a");
-	if (!f)
-		return -1;
+	if (!f) {
+		ast_mutex_unlock(&acf_lock);
+		ast_log(LOG_ERROR, "Unable to open file %s : %s\n", tmp, strerror(errno));
+		return -1;
+	}
 	fputs(s, f);
 	fflush(f);
 	fclose(f);
+	ast_mutex_unlock(&acf_lock);
+
 	return 0;
 }
 
 
 static int csv_log(struct ast_cdr *cdr)
 {
+	FILE *mf = NULL;
 	/* Make sure we have a big enough buf */
 	char buf[1024];
 	char csvmaster[PATH_MAX];
@@ -291,16 +300,19 @@
 		/* because of the absolutely unconditional need for the
 		   highest reliability possible in writing billing records,
 		   we open write and close the log file each time */
+		ast_mutex_lock(&mf_lock);
 		mf = fopen(csvmaster, "a");
-		if (!mf) {
-			ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
-		}
 		if (mf) {
 			fputs(buf, mf);
 			fflush(mf); /* be particularly anal here */
 			fclose(mf);
 			mf = NULL;
-		}
+			ast_mutex_unlock(&mf_lock);
+		} else {
+			ast_mutex_unlock(&mf_lock);
+			ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
+		}
+
 		if (!ast_strlen_zero(cdr->accountcode)) {
 			if (writefile(buf, cdr->accountcode))
 				ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno));
@@ -311,8 +323,6 @@
 
 static int unload_module(void)
 {
-	if (mf)
-		fclose(mf);
 	ast_cdr_unregister(name);
 	return 0;
 }
@@ -327,8 +337,6 @@
 	res = ast_cdr_register(name, ast_module_info->description, csv_log);
 	if (res) {
 		ast_log(LOG_ERROR, "Unable to register CSV CDR handling\n");
-		if (mf)
-			fclose(mf);
 	}
 	return res;
 }




More information about the asterisk-commits mailing list