From 95712c847e3f90209ac7489def74f530acb0addf Mon Sep 17 00:00:00 2001 From: russell Date: Wed, 25 Jan 2006 18:24:32 +0000 Subject: 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 --- channels/chan_features.c | 87 ++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 51 deletions(-) (limited to 'channels/chan_features.c') 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 : "", 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; } -- cgit v1.2.3