[asterisk-commits] twilson: trunk r324050 - in /trunk: ./ channels/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jun 16 17:49:54 CDT 2011


Author: twilson
Date: Thu Jun 16 17:49:49 2011
New Revision: 324050

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=324050
Log:
Merged revisions 324048 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r324048 | twilson | 2011-06-16 17:35:41 -0500 (Thu, 16 Jun 2011) | 8 lines
  
  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:
    trunk/   (props changed)
    trunk/channels/chan_local.c
    trunk/channels/chan_sip.c
    trunk/include/asterisk/channel.h
    trunk/main/channel.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: trunk/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_local.c?view=diff&rev=324050&r1=324049&r2=324050
==============================================================================
--- trunk/channels/chan_local.c (original)
+++ trunk/channels/chan_local.c Thu Jun 16 17:49:49 2011
@@ -217,6 +217,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;
@@ -225,27 +226,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);
@@ -272,6 +268,7 @@
 	if (otherchan) {
 		ast_channel_unref(otherchan);
 	}
+	ast_channel_lock(ast); /* Lock back before we leave */
 	return res;
 }
 
@@ -348,6 +345,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;
@@ -361,21 +359,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))) {
@@ -394,6 +389,7 @@
 	if (tmp) {
 		tmp = ast_channel_unref(tmp);
 	}
+	ast_channel_lock(ast); /* Lock back before we leave */
 
 	return res;
 }

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=324050&r1=324049&r2=324050
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Jun 16 17:49:49 2011
@@ -4262,15 +4262,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, (struct ast_format *) data);
+		if (p->rtp) {
+			res = ast_rtp_instance_set_read_format(p->rtp, (struct ast_format *) data);
+		}
 		break;
 	case AST_OPTION_FORMAT_WRITE:
-		res = ast_rtp_instance_set_write_format(p->rtp, (struct ast_format *) data);
+		if (p->rtp) {
+			res = ast_rtp_instance_set_write_format(p->rtp, (struct ast_format *) 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) ||
@@ -4298,6 +4306,8 @@
 		break;
 	}
 
+	sip_pvt_unlock(p);
+
 	return res;
 }
 
@@ -4308,16 +4318,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)) {
@@ -4336,8 +4346,6 @@
 				state = T38_STATE_UNKNOWN;
 			}
 		}
-
-		sip_pvt_unlock(p);
 
 		*((enum ast_t38_state *) data) = state;
 		res = 0;
@@ -4369,6 +4377,8 @@
 	default:
 		break;
 	}
+
+	sip_pvt_unlock(p);
 
 	return res;
 }

Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=324050&r1=324049&r2=324050
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Thu Jun 16 17:49:49 2011
@@ -576,10 +576,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: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=324050&r1=324049&r2=324050
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Thu Jun 16 17:49:49 2011
@@ -7608,28 +7608,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