[asterisk-commits] juggie: branch juggie/NoLossCDR r84113 - /team/juggie/NoLossCDR/main/cdr.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Sep 28 17:01:21 CDT 2007


Author: juggie
Date: Fri Sep 28 17:01:21 2007
New Revision: 84113

URL: http://svn.digium.com/view/asterisk?view=rev&rev=84113
Log:
fix a race condition

Modified:
    team/juggie/NoLossCDR/main/cdr.c

Modified: team/juggie/NoLossCDR/main/cdr.c
URL: http://svn.digium.com/view/asterisk/team/juggie/NoLossCDR/main/cdr.c?view=diff&rev=84113&r1=84112&r2=84113
==============================================================================
--- team/juggie/NoLossCDR/main/cdr.c (original)
+++ team/juggie/NoLossCDR/main/cdr.c Fri Sep 28 17:01:21 2007
@@ -715,21 +715,27 @@
 	ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
 	if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
 		return;
+	/* add a ref to make sure we dont have a weird race condition */
+	ast_atomic_fetchadd_int(&cdr->usecount, +1);
 	AST_RWLIST_RDLOCK(&be_list);
 	AST_RWLIST_TRAVERSE(&be_list, i, list) {
 		AST_LIST_LOCK(&i->cdr_queue);
 		ast_debug(1, "cdr inserted into queue/list for: %s\n", i->name);
 		/* increment usecount of this cdr record */
 		ast_atomic_fetchadd_int(&cdr->usecount, +1);
-		//ast_update_use_count();
 		/* increment cdr counter for this queue */
 		ast_atomic_fetchadd_int(&i->waiting_cdrs, +1);
-		//ast_update_use_count();
 		AST_LIST_INSERT_TAIL(&i->cdr_queue, cdr, list);
 		ast_cond_signal(&i->cdr_pending_cond);
 		AST_LIST_UNLOCK(&i->cdr_queue);
 	}
 	AST_RWLIST_UNLOCK(&be_list);
+	ast_atomic_fetchadd_int(&cdr->usecount, -1);
+	if (ast_atomic_fetchadd_int(&cdr->usecount, -1) == 1) {
+		ast_debug(1, "cdr record no longer in any queue, so lets free it\n");
+		ast_cdr_free(cdr);
+	}
+
 }
 
 void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *_flags)
@@ -855,6 +861,9 @@
 			ast_atomic_fetchadd_int(&i->waiting_cdrs, -1);
 			/* depracate uses of this cdr record
 			free if no one is using it*/
+			/* there is a race condition here, if one thread finishes working on the cdr before
+			it is posted to all the backends, then it will delete the cdr before we are actually
+			finished with it and an explosion occurs */ 
 			if (ast_atomic_fetchadd_int(&cdr->usecount, -1) == 1) {
 				ast_debug(1, "cdr record no longer in any queue, so lets free it\n");
 				ast_cdr_free(cdr);




More information about the asterisk-commits mailing list