[asterisk-commits] trunk r8665 - /trunk/channels/chan_features.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Jan 25 11:24:36 MST 2006


Author: russell
Date: Wed Jan 25 12:24:32 2006
New Revision: 8665

URL: http://svn.digium.com/view/asterisk?rev=8665&view=rev
Log:
store feature_pvt list using linked list macros
(issue #6351, with additional changes to prevent a memory leak in unload_module)

Modified:
    trunk/channels/chan_features.c

Modified: trunk/channels/chan_features.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_features.c?rev=8665&r1=8664&r2=8665&view=diff
==============================================================================
--- trunk/channels/chan_features.c (original)
+++ trunk/channels/chan_features.c Wed Jan 25 12:24:32 2006
@@ -71,9 +71,6 @@
 
 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
 
-/* Protect the interface list (of feature_pvt's) */
-AST_MUTEX_DEFINE_STATIC(featurelock);
-
 struct feature_sub {
 	struct ast_channel *owner;
 	int inthreeway;
@@ -82,15 +79,17 @@
 	int alertpipebackup[2];
 };
 
-static struct feature_pvt {
+struct feature_pvt {
 	ast_mutex_t lock;			/* Channel private lock */
 	char tech[AST_MAX_EXTENSION];		/* Technology to abstract */
 	char dest[AST_MAX_EXTENSION];		/* Destination to abstract */
 	struct ast_channel *subchan;
 	struct feature_sub subs[3];		/* Subs */
 	struct ast_channel *owner;		/* Current Master Channel */
-	struct feature_pvt *next;		/* Next entity */
-} *features = NULL;
+	AST_LIST_ENTRY(feature_pvt) list;	/* Next entity */
+};
+
+static AST_LIST_HEAD_STATIC(features, feature_pvt);
 
 #define SUB_REAL	0			/* Active call */
 #define SUB_CALLWAIT	1			/* Call-Waiting call on hold */
@@ -366,7 +365,6 @@
 static int features_hangup(struct ast_channel *ast)
 {
 	struct feature_pvt *p = ast->tech_pvt;
-	struct feature_pvt *cur, *prev=NULL;
 	int x;
 
 	ast_mutex_lock(&p->lock);
@@ -378,24 +376,12 @@
 	}
 	ast->tech_pvt = NULL;
 	
-	
 	if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
 		ast_mutex_unlock(&p->lock);
 		/* Remove from list */
-		ast_mutex_lock(&featurelock);
-		cur = features;
-		while(cur) {
-			if (cur == p) {
-				if (prev)
-					prev->next = cur->next;
-				else
-					features = cur->next;
-				break;
-			}
-			prev = cur;
-			cur = cur->next;
-		}
-		ast_mutex_unlock(&featurelock);
+		AST_LIST_LOCK(&features);
+		AST_LIST_REMOVE(&features, p, list);
+		AST_LIST_UNLOCK(&features);
 		ast_mutex_lock(&p->lock);
 		/* And destroy */
 		if (p->subchan)
@@ -431,14 +417,12 @@
 			data);
 		return NULL;
 	}
-	ast_mutex_lock(&featurelock);
-	tmp = features;
-	while(tmp) {
+	AST_LIST_LOCK(&features);
+	AST_LIST_TRAVERSE(&features, tmp, list) {
 		if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest))
 			break;
-		tmp = tmp->next;
-	}
-	ast_mutex_unlock(&featurelock);
+	}
+	AST_LIST_UNLOCK(&features);
 	if (!tmp) {
 		chan = ast_request(tech, format, dest, &status);
 		if (!chan) {
@@ -454,10 +438,9 @@
 			strncpy(tmp->tech, tech, sizeof(tmp->tech) - 1);
 			strncpy(tmp->dest, dest, sizeof(tmp->dest) - 1);
 			tmp->subchan = chan;
-			ast_mutex_lock(&featurelock);
-			tmp->next = features;
-			features = tmp;
-			ast_mutex_unlock(&featurelock);
+			AST_LIST_LOCK(&features);
+			AST_LIST_INSERT_HEAD(&features, tmp, list);
+			AST_LIST_UNLOCK(&features);
 		}
 	}
 	return tmp;
@@ -530,17 +513,19 @@
 
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
-	ast_mutex_lock(&featurelock);
-	p = features;
-	while(p) {
+
+	if (AST_LIST_EMPTY(&features)) {
+		ast_cli(fd, "No feature channels in use\n");
+		return RESULT_SUCCESS;
+	}
+
+	AST_LIST_LOCK(&features);
+	AST_LIST_TRAVERSE(&features, p, list) {
 		ast_mutex_lock(&p->lock);
 		ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest);
 		ast_mutex_unlock(&p->lock);
-		p = p->next;
-	}
-	if (!features)
-		ast_cli(fd, "No feature channels in use\n");
-	ast_mutex_unlock(&featurelock);
+	}
+	AST_LIST_UNLOCK(&features);
 	return RESULT_SUCCESS;
 }
 
@@ -571,23 +556,23 @@
 int unload_module()
 {
 	struct feature_pvt *p;
+	
 	/* First, take us out of the channel loop */
 	ast_cli_unregister(&cli_show_features);
 	ast_channel_unregister(&features_tech);
-	if (!ast_mutex_lock(&featurelock)) {
-		/* Hangup all interfaces if they have an owner */
-		p = features;
-		while(p) {
-			if (p->owner)
-				ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
-			p = p->next;
-		}
-		features = NULL;
-		ast_mutex_unlock(&featurelock);
-	} else {
-		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+	
+	if (!AST_LIST_LOCK(&features))
 		return -1;
-	}		
+	/* Hangup all interfaces if they have an owner */
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&features, p, list) {
+		if (p->owner)
+			ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
+		AST_LIST_REMOVE_CURRENT(&features, list);
+		free(p);
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+	AST_LIST_UNLOCK(&features);
+	
 	return 0;
 }
 



More information about the asterisk-commits mailing list