aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_features.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2006-01-25 18:24:32 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2006-01-25 18:24:32 +0000
commit95712c847e3f90209ac7489def74f530acb0addf (patch)
tree01db76a7629e0cccc0b757f2efa02b1a2bc94de8 /channels/chan_features.c
parent5b838d569d176d1cc4a4f3ab9af58d8c4f930482 (diff)
store feature_pvt list using linked list macros
(issue #6351, with additional changes to prevent a memory leak in unload_module) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@8665 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_features.c')
-rw-r--r--channels/chan_features.c87
1 files changed, 36 insertions, 51 deletions
diff --git a/channels/chan_features.c b/channels/chan_features.c
index 3f7ac9f49..dc2b70a10 100644
--- a/channels/chan_features.c
+++ b/channels/chan_features.c
@@ -71,9 +71,6 @@ AST_MUTEX_DEFINE_STATIC(usecnt_lock);
#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 @@ struct feature_sub {
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_call(struct ast_channel *ast, char *dest, int timeout)
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 @@ static int features_hangup(struct ast_channel *ast)
}
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 @@ static struct feature_pvt *features_alloc(char *data, int format)
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 @@ static struct feature_pvt *features_alloc(char *data, int format)
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 @@ static int features_show(int fd, int argc, char **argv)
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 reload()
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;
}