[asterisk-commits] twilson: branch 1.8 r324048 - in /branches/1.8: channels/ include/asterisk/ m...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jun 16 17:35:47 CDT 2011
Author: twilson
Date: Thu Jun 16 17:35:41 2011
New Revision: 324048
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=324048
Log:
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/
Modified:
branches/1.8/channels/chan_local.c
branches/1.8/channels/chan_sip.c
branches/1.8/include/asterisk/channel.h
branches/1.8/main/channel.c
Modified: branches/1.8/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/channels/chan_local.c?view=diff&rev=324048&r1=324047&r2=324048
==============================================================================
--- branches/1.8/channels/chan_local.c (original)
+++ branches/1.8/channels/chan_local.c Thu Jun 16 17:35:41 2011
@@ -218,6 +218,7 @@
*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 @@
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 @@
if (otherchan) {
ast_channel_unref(otherchan);
}
+ ast_channel_lock(ast); /* Lock back before we leave */
return res;
}
@@ -349,6 +346,7 @@
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 @@
}
/* 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 @@
if (tmp) {
tmp = ast_channel_unref(tmp);
}
+ ast_channel_lock(ast); /* Lock back before we leave */
return res;
}
Modified: branches/1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/channels/chan_sip.c?view=diff&rev=324048&r1=324047&r2=324048
==============================================================================
--- branches/1.8/channels/chan_sip.c (original)
+++ branches/1.8/channels/chan_sip.c Thu Jun 16 17:35:41 2011
@@ -4226,15 +4226,23 @@
int res = -1;
struct sip_pvt *p = chan->tech_pvt;
+ sip_pvt_lock(p);
+
switch (option) {
case AST_OPTION_FORMAT_READ:
- res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data);
+ if (p->rtp) {
+ res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data);
+ }
break;
case AST_OPTION_FORMAT_WRITE:
- res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data);
+ if (p->rtp) {
+ res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data);
+ }
break;
case AST_OPTION_MAKE_COMPATIBLE:
- res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data);
+ if (p->rtp) {
+ res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data);
+ }
break;
case AST_OPTION_DIGIT_DETECT:
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
@@ -4262,6 +4270,8 @@
break;
}
+ sip_pvt_unlock(p);
+
return res;
}
@@ -4272,16 +4282,16 @@
enum ast_t38_state state = T38_STATE_UNAVAILABLE;
struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt;
char *cp;
+
+ sip_pvt_lock(p);
switch (option) {
case AST_OPTION_T38_STATE:
/* Make sure we got an ast_t38_state enum passed in */
if (*datalen != sizeof(enum ast_t38_state)) {
ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option. Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen);
- return -1;
- }
-
- sip_pvt_lock(p);
+ break;
+ }
/* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
@@ -4297,8 +4307,6 @@
state = T38_STATE_UNKNOWN;
}
}
-
- sip_pvt_unlock(p);
*((enum ast_t38_state *) data) = state;
res = 0;
@@ -4330,6 +4338,8 @@
default:
break;
}
+
+ sip_pvt_unlock(p);
return res;
}
Modified: branches/1.8/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/include/asterisk/channel.h?view=diff&rev=324048&r1=324047&r2=324048
==============================================================================
--- branches/1.8/include/asterisk/channel.h (original)
+++ branches/1.8/include/asterisk/channel.h Thu Jun 16 17:35:41 2011
@@ -572,10 +572,10 @@
/*! \brief Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links */
int (* const fixup)(struct ast_channel *oldchan, struct ast_channel *newchan);
- /*! \brief Set a given option */
+ /*! \brief Set a given option. Called with chan locked */
int (* const setoption)(struct ast_channel *chan, int option, void *data, int datalen);
- /*! \brief Query a given option */
+ /*! \brief Query a given option. Called with chan locked */
int (* const queryoption)(struct ast_channel *chan, int option, void *data, int *datalen);
/*! \brief Blind transfer other side (see app_transfer.c and ast_transfer() */
Modified: branches/1.8/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/channel.c?view=diff&rev=324048&r1=324047&r2=324048
==============================================================================
--- branches/1.8/main/channel.c (original)
+++ branches/1.8/main/channel.c Thu Jun 16 17:35:41 2011
@@ -7387,28 +7387,42 @@
/*! \brief Sets an option on a channel */
int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block)
{
+ int res;
+
+ ast_channel_lock(chan);
if (!chan->tech->setoption) {
errno = ENOSYS;
+ ast_channel_unlock(chan);
return -1;
}
if (block)
ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
- return chan->tech->setoption(chan, option, data, datalen);
+ res = chan->tech->setoption(chan, option, data, datalen);
+ ast_channel_unlock(chan);
+
+ return res;
}
int ast_channel_queryoption(struct ast_channel *chan, int option, void *data, int *datalen, int block)
{
+ int res;
+
+ ast_channel_lock(chan);
if (!chan->tech->queryoption) {
errno = ENOSYS;
+ ast_channel_unlock(chan);
return -1;
}
if (block)
ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
- return chan->tech->queryoption(chan, option, data, datalen);
+ res = chan->tech->queryoption(chan, option, data, datalen);
+ ast_channel_unlock(chan);
+
+ return res;
}
struct tonepair_def {
More information about the asterisk-commits
mailing list