Lock the channel before calling the setoption callback

The channel needs to be locked before calling these callback functions. Also,
sip_setoption needs to lock the pvt and a check p->rtp is non-null before using
it.

Review: https://reviewboard.asterisk.org/r/1220/


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@324048 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Terry Wilson
2011-06-16 22:35:41 +00:00
parent cf2d1b01be
commit c84e7b911e
4 changed files with 45 additions and 25 deletions

View File

@@ -218,6 +218,7 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s
*outchan = p->chan;
}
/* Called with ast locked */
static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen)
{
int res = 0;
@@ -226,27 +227,22 @@ static int local_setoption(struct ast_channel *ast, int option, void * data, int
ast_chan_write_info_t *write_info;
if (option != AST_OPTION_CHANNEL_WRITE) {
res = -1;
goto setoption_cleanup;
return -1;
}
write_info = data;
if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
res = -1;
goto setoption_cleanup;
return -1
}
/* get the tech pvt */
ast_channel_lock(ast);
if (!(p = ast->tech_pvt)) {
ast_channel_unlock(ast);
res = -1;
goto setoption_cleanup;
return -1;
}
ao2_ref(p, 1);
ast_channel_unlock(ast);
ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
/* get the channel we are supposed to write to */
ao2_lock(p);
@@ -273,6 +269,7 @@ setoption_cleanup:
if (otherchan) {
ast_channel_unref(otherchan);
}
ast_channel_lock(ast); /* Lock back before we leave */
return res;
}
@@ -349,6 +346,7 @@ static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct
return bridged;
}
/* Called with ast locked */
static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
{
struct local_pvt *p;
@@ -362,21 +360,18 @@ static int local_queryoption(struct ast_channel *ast, int option, void *data, in
}
/* for some reason the channel is not locked in channel.c when this function is called */
ast_channel_lock(ast);
if (!(p = ast->tech_pvt)) {
ast_channel_unlock(ast);
return -1;
}
ao2_lock(p);
if (!(tmp = IS_OUTBOUND(ast, p) ? p->owner : p->chan)) {
ao2_unlock(p);
ast_channel_unlock(ast);
return -1;
}
ast_channel_ref(tmp);
ao2_unlock(p);
ast_channel_unlock(ast);
ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
ast_channel_lock(tmp);
if (!(bridged = ast_bridged_channel(tmp))) {
@@ -395,6 +390,7 @@ query_cleanup:
if (tmp) {
tmp = ast_channel_unref(tmp);
}
ast_channel_lock(ast); /* Lock back before we leave */
return res;
}