diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-05-20 16:30:10 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-05-20 16:30:10 +0000 |
commit | ec76498f552e4ff10adcaa0ffc27d1c21cb5792e (patch) | |
tree | efbb775d4f7e80cb61b314075217774d082e881a | |
parent | 7e42c962d89de0673789eed30649fc7ae276aa50 (diff) |
Make ast_channel_walk become ast_channel_walk_locked
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3029 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-x | apps/app_agi.c | 16 | ||||
-rwxr-xr-x | apps/app_groupcount.c | 9 | ||||
-rwxr-xr-x | apps/app_setcdruserfield.c | 6 | ||||
-rwxr-xr-x | apps/app_softhangup.c | 6 | ||||
-rwxr-xr-x | apps/app_zapscan.c | 76 | ||||
-rwxr-xr-x | channel.c | 18 | ||||
-rwxr-xr-x | channels/chan_mgcp.c | 2 | ||||
-rwxr-xr-x | cli.c | 50 | ||||
-rwxr-xr-x | include/asterisk/channel.h | 3 | ||||
-rwxr-xr-x | manager.c | 17 | ||||
-rwxr-xr-x | pbx.c | 16 | ||||
-rwxr-xr-x | res/res_monitor.c | 21 | ||||
-rwxr-xr-x | res/res_parking.c | 6 |
13 files changed, 152 insertions, 94 deletions
diff --git a/apps/app_agi.c b/apps/app_agi.c index ba479b28e..d7af708b4 100755 --- a/apps/app_agi.c +++ b/apps/app_agi.c @@ -692,15 +692,17 @@ static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **ar return RESULT_SUCCESS; } else if (argc==2) { /* one argument: look for info on the specified channel */ - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while (c) { if (strcasecmp(argv[1],c->name)==0) { /* we have a matching channel */ - ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); - fdprintf(agi->fd, "200 result=1\n"); + ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); + fdprintf(agi->fd, "200 result=1\n"); + ast_mutex_unlock(&c->lock); return RESULT_SUCCESS; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } /* if we get this far no channel name matched the argument given */ fdprintf(agi->fd, "200 result=-1\n"); @@ -753,13 +755,15 @@ static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, ch return RESULT_SUCCESS; } else if (argc==3) { /* one argument: look for info on the specified channel */ - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while (c) { if (strcasecmp(argv[2],c->name)==0) { fdprintf(agi->fd, "200 result=%d\n", c->_state); + ast_mutex_unlock(&c->lock); return RESULT_SUCCESS; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } /* if we get this far no channel name matched the argument given */ fdprintf(agi->fd, "200 result=-1\n"); diff --git a/apps/app_groupcount.c b/apps/app_groupcount.c index ef7b92cd9..b97a77466 100755 --- a/apps/app_groupcount.c +++ b/apps/app_groupcount.c @@ -58,20 +58,17 @@ LOCAL_USER_DECL; static int group_get_count(char *group) { - /* XXX ast_channel_walk needs to be modified to - prevent a race in which after we return the channel - is no longer valid (or ast_channel_free can be modified - just as well) XXX */ struct ast_channel *chan; int count = 0; char *test; if (group && !ast_strlen_zero(group)) { - chan = ast_channel_walk(NULL); + chan = ast_channel_walk_locked(NULL); while(chan) { test = pbx_builtin_getvar_helper(chan, "GROUP"); if (test && !strcasecmp(test, group)) count++; - chan = ast_channel_walk(chan); + ast_mutex_unlock(&chan->lock); + chan = ast_channel_walk_locked(chan); } } return count; diff --git a/apps/app_setcdruserfield.c b/apps/app_setcdruserfield.c index bb1bb339e..d0ebd2e13 100755 --- a/apps/app_setcdruserfield.c +++ b/apps/app_setcdruserfield.c @@ -76,11 +76,12 @@ static int action_setcdruserfield(struct mansession *s, struct message *m) astman_send_error(s, m, "No UserField specified"); return 0; } - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while (c) { if (!strcasecmp(c->name, channel)) break; - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) { astman_send_error(s, m, "No such channel"); @@ -90,6 +91,7 @@ static int action_setcdruserfield(struct mansession *s, struct message *m) ast_cdr_appenduserfield(c, userfield); else ast_cdr_setuserfield(c, userfield); + ast_mutex_unlock(&c->lock); astman_send_ack(s, m, "CDR Userfield Set"); return 0; } diff --git a/apps/app_softhangup.c b/apps/app_softhangup.c index 497f03860..43a42247c 100755 --- a/apps/app_softhangup.c +++ b/apps/app_softhangup.c @@ -47,13 +47,15 @@ static int softhangup_exec(struct ast_channel *chan, void *data) return 0; } LOCAL_USER_ADD(u); - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while (c) { if (!strcasecmp(c->name, data)) { ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT); + ast_mutex_unlock(&c->lock); break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } LOCAL_USER_REMOVE(u); diff --git a/apps/app_zapscan.c b/apps/app_zapscan.c index ab87f592c..58a456f38 100755 --- a/apps/app_zapscan.c +++ b/apps/app_zapscan.c @@ -54,17 +54,18 @@ LOCAL_USER_DECL; #define CONF_SIZE 160 -static struct ast_channel *get_zap_channel(int num) { +static struct ast_channel *get_zap_channel_locked(int num) { struct ast_channel *c=NULL; char name[80]; snprintf(name,sizeof(name),"Zap/%d-1",num); - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, name)) { break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (c) return c; @@ -293,43 +294,44 @@ static int conf_exec(struct ast_channel *chan, void *data) ast_answer(chan); for (;;) { - if (ast_waitfor(chan, 100) < 0) - break; - f = ast_read(chan); - if (!f) - break; - if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { + if (ast_waitfor(chan, 100) < 0) + break; + + f = ast_read(chan); + if (!f) + break; + if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { + ast_frfree(f); + break; + } ast_frfree(f); - break; - } - ast_frfree(f); - ichan = NULL; - if(input) { - ichan = get_zap_channel(input); - input = 0; - } - - tempchan = ichan ? ichan : ast_channel_walk(tempchan); - - - if ( !tempchan && !lastchan ) - break; - if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) { - ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name); - strcpy(confstr, tempchan->name); - if ((tmp = strchr(confstr,'-'))) { - *tmp = '\0'; + ichan = NULL; + if(input) { + ichan = get_zap_channel_locked(input); + input = 0; } - confno = atoi(strchr(confstr,'/') + 1); - ast_stopstream(chan); - ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL); - res = conf_run(chan, confno, confflags); - if (res<0) break; - input = res; - } - lastchan = tempchan; + + tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan); + + + if ( !tempchan && !lastchan ) + break; + if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) { + ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name); + strcpy(confstr, tempchan->name); + ast_mutex_unlock(&tempchan->lock); + if ((tmp = strchr(confstr,'-'))) { + *tmp = '\0'; + } + confno = atoi(strchr(confstr,'/') + 1); + ast_stopstream(chan); + ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL); + res = conf_run(chan, confno, confflags); + if (res<0) break; + input = res; + } + lastchan = tempchan; } - LOCAL_USER_REMOVE(u); return res; } @@ -444,12 +444,15 @@ void ast_channel_undefer_dtmf(struct ast_channel *chan) chan->deferdtmf = 0; } -struct ast_channel *ast_channel_walk(struct ast_channel *prev) +struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev) { + /* Returns next channel (locked) */ struct ast_channel *l, *ret=NULL; ast_mutex_lock(&chlock); l = channels; if (!prev) { + if (l) + ast_mutex_lock(&l->lock); ast_mutex_unlock(&chlock); return l; } @@ -458,6 +461,8 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev) ret = l->next; l = l->next; } + if (ret) + ast_mutex_lock(&ret->lock); ast_mutex_unlock(&chlock); return ret; @@ -527,6 +532,12 @@ void ast_channel_free(struct ast_channel *chan) } if (!cur) ast_log(LOG_WARNING, "Unable to find channel in list\n"); + else { + /* Lock and unlock the channel just to be sure nobody + has it locked still */ + ast_mutex_lock(&cur->lock); + ast_mutex_unlock(&cur->lock); + } if (chan->pvt->pvt) ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); @@ -1798,15 +1809,16 @@ int ast_parse_device_state(char *device) char *cut; struct ast_channel *chan; - chan = ast_channel_walk(NULL); + chan = ast_channel_walk_locked(NULL); while (chan) { strncpy(name, chan->name, sizeof(name)-1); + ast_mutex_unlock(&chan->lock); cut = strchr(name,'-'); if (cut) *cut = 0; if (!strcmp(name, device)) return AST_DEVICE_INUSE; - chan = ast_channel_walk(chan); + chan = ast_channel_walk_locked(chan); } return AST_DEVICE_UNKNOWN; } diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 5b7d0cf40..ea299187c 100755 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -1764,6 +1764,8 @@ static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb { memset(req, 0, sizeof(struct mgcp_request)); oseq++; + if (oseq > 999999999) + oseq = 1; init_req(p, req, verb); return 0; } @@ -291,13 +291,14 @@ static int handle_chanlist(int fd, int argc, char *argv[]) int numchans = 0; if (argc != 2) return RESULT_SHOWUSAGE; - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); ast_cli(fd, FORMAT_STRING2, "Channel", "Context", "Extension", "Pri", "State", "Appl.", "Data"); while(c) { ast_cli(fd, FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state), c->appl ? c->appl : "(None)", c->data ? ( !ast_strlen_zero(c->data) ? c->data : "(Empty)" ): "(None)"); numchans++; - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } ast_cli(fd, "%d active channel(s)\n", numchans); return RESULT_SUCCESS; @@ -335,14 +336,16 @@ static int handle_softhangup(int fd, int argc, char *argv[]) struct ast_channel *c=NULL; if (argc != 3) return RESULT_SHOWUSAGE; - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, argv[2])) { ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name); ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT); + ast_mutex_unlock(&c->lock); break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) ast_cli(fd, "%s is not a known channel\n", argv[2]); @@ -438,17 +441,20 @@ static int handle_debugchan(int fd, int argc, char *argv[]) struct ast_channel *c=NULL; if (argc != 3) return RESULT_SHOWUSAGE; - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, argv[2])) { c->fin |= 0x80000000; c->fout |= 0x80000000; break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } - if (c) + if (c) { ast_cli(fd, "Debugging enabled on channel %s\n", c->name); + ast_mutex_unlock(&c->lock); + } else ast_cli(fd, "No such channel %s\n", argv[2]); return RESULT_SUCCESS; @@ -459,18 +465,20 @@ static int handle_nodebugchan(int fd, int argc, char *argv[]) struct ast_channel *c=NULL; if (argc != 4) return RESULT_SHOWUSAGE; - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, argv[3])) { c->fin &= 0x7fffffff; c->fout &= 0x7fffffff; break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } - if (c) + if (c) { ast_cli(fd, "Debugging disabled on channel %s\n", c->name); - else + ast_mutex_unlock(&c->lock); + } else ast_cli(fd, "No such channel %s\n", argv[2]); return RESULT_SUCCESS; } @@ -482,7 +490,7 @@ static int handle_showchan(int fd, int argc, char *argv[]) struct ast_channel *c=NULL; if (argc != 3) return RESULT_SHOWUSAGE; - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, argv[2])) { ast_cli(fd, @@ -519,10 +527,11 @@ static int handle_showchan(int fd, int argc, char *argv[]) c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ), ( c-> data ? (!ast_strlen_zero(c->data) ? c->data : "(Empty)") : "(None)"), c->stack, (c->blocking ? c->blockproc : "(Not Blocking)")); - + ast_mutex_unlock(&c->lock); break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) ast_cli(fd, "%s is not a known channel\n", argv[2]); @@ -533,15 +542,22 @@ static char *complete_ch(char *line, char *word, int pos, int state) { struct ast_channel *c; int which=0; - c = ast_channel_walk(NULL); + char *ret; + c = ast_channel_walk_locked(NULL); while(c) { if (!strncasecmp(word, c->name, strlen(word))) { if (++which > state) break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } - return c ? strdup(c->name) : NULL; + if (c) { + ret = strdup(c->name); + ast_mutex_unlock(&c->lock); + } else + ret = NULL; + return ret; } static char *complete_fn(char *line, char *word, int pos, int state) diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index e420a1982..baae96213 100755 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -624,8 +624,9 @@ int ast_recvchar(struct ast_channel *chan, int timeout); * \param prev where you want to start in the channel list * Browse the channels currently in use * Returns the next channel in the list, NULL on end. + * If it returns a channel, that channel *has been locked*! */ -struct ast_channel *ast_channel_walk(struct ast_channel *prev); +struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev); //! Waits for a digit /*! @@ -376,18 +376,20 @@ static int action_hangup(struct mansession *s, struct message *m) astman_send_error(s, m, "No channel specified"); return 0; } - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, name)) { break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) { astman_send_error(s, m, "No such channel"); return 0; } ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT); + ast_mutex_unlock(&c->lock); astman_send_ack(s, m, "Channel Hungup"); return 0; } @@ -399,7 +401,7 @@ static int action_status(struct mansession *s, struct message *m) struct ast_channel *c; char bridge[256]; astman_send_ack(s, m, "Channel status will follow"); - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); if (id && strlen(id)) snprintf(idText,256,"ActionID: %s\r\n",id); while(c) { @@ -436,7 +438,8 @@ static int action_status(struct mansession *s, struct message *m) c->name, c->callerid ? c->callerid : "<unknown>", ast_state2str(c->_state), bridge, c->uniqueid, idText); } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } ast_cli(s->fd, "Event: StatusComplete\r\n" @@ -688,18 +691,20 @@ static int action_timeout(struct mansession *s, struct message *m) astman_send_error(s, m, "No timeout specified"); return 0; } - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, name)) { break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) { astman_send_error(s, m, "No such channel"); return 0; } ast_channel_setwhentohangup(c, timeout); + ast_mutex_unlock(&c->lock); astman_send_ack(s, m, "Timeout Set"); return 0; } @@ -3592,15 +3592,21 @@ int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int pri int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority) { struct ast_channel *chan; - chan = ast_channel_walk(NULL); + int res = -1; + + chan = ast_channel_walk_locked(NULL); while(chan) { if (!strcasecmp(channame, chan->name)) break; - chan = ast_channel_walk(chan); + ast_mutex_unlock(&chan->lock); + chan = ast_channel_walk_locked(chan); } - if (chan) - return ast_async_goto(chan, context, exten, priority); - return -1; + + if (chan) { + res = ast_async_goto(chan, context, exten, priority); + ast_mutex_unlock(&chan->lock); + } + return res; } static void ext_strncpy(char *dst, char *src, int len) diff --git a/res/res_monitor.c b/res/res_monitor.c index 22e365d08..3d7217090 100755 --- a/res/res_monitor.c +++ b/res/res_monitor.c @@ -333,12 +333,13 @@ static int start_monitor_action(struct mansession *s, struct message *m) astman_send_error(s, m, "No channel specified"); return 0; } - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, name)) { break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) { astman_send_error(s, m, "No such channel"); @@ -360,6 +361,7 @@ static int start_monitor_action(struct mansession *s, struct message *m) return 0; } } + ast_mutex_unlock(&c->lock); astman_send_ack(s, m, "Started monitoring channel"); return 0; } @@ -368,22 +370,26 @@ static int stop_monitor_action(struct mansession *s, struct message *m) { struct ast_channel *c = NULL; char *name = astman_get_header(m, "Channel"); + int res; if((!name)||(!strlen(name))) { astman_send_error(s, m, "No channel specified"); return 0; } - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, name)) { break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) { astman_send_error(s, m, "No such channel"); return 0; } - if( ast_monitor_stop( c, 1 ) ) { + res = ast_monitor_stop( c, 1 ); + ast_mutex_unlock(&c->lock); + if( res ) { astman_send_error(s, m, "Could not stop monitoring channel"); return 0; } @@ -404,12 +410,13 @@ static int change_monitor_action(struct mansession *s, struct message *m) astman_send_error(s, m, "No filename specified"); return 0; } - c = ast_channel_walk(NULL); + c = ast_channel_walk_locked(NULL); while(c) { if (!strcasecmp(c->name, name)) { break; } - c = ast_channel_walk(c); + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); } if (!c) { astman_send_error(s, m, "No such channel"); diff --git a/res/res_parking.c b/res/res_parking.c index 29b63684c..e63f490cb 100755 --- a/res/res_parking.c +++ b/res/res_parking.c @@ -737,7 +737,7 @@ int ast_pickup_call(struct ast_channel *chan) { struct ast_channel *cur; int res = -1; - cur = ast_channel_walk(NULL); + cur = ast_channel_walk_locked(NULL); while(cur) { if (!cur->pbx && (cur != chan) && @@ -746,7 +746,8 @@ int ast_pickup_call(struct ast_channel *chan) (cur->_state == AST_STATE_RING))) { break; } - cur = ast_channel_walk(cur); + ast_mutex_unlock(&cur->lock); + cur = ast_channel_walk_locked(cur); } if (cur) { ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); @@ -759,6 +760,7 @@ int ast_pickup_call(struct ast_channel *chan) res = ast_channel_masquerade(cur, chan); if (res) ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ + ast_mutex_unlock(&cur->lock); } else { ast_log(LOG_DEBUG, "No call pickup possible...\n"); } |