[asterisk-commits] dvossel: branch dvossel/masq_locking_order_trunk r221392 - in /team/dvossel/m...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Sep 30 15:23:19 CDT 2009
Author: dvossel
Date: Wed Sep 30 15:23:14 2009
New Revision: 221392
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=221392
Log:
This commit is my initial try at eliminating all channel locks
before a masquerade is issued.
Modified:
team/dvossel/masq_locking_order_trunk/channels/chan_sip.c
team/dvossel/masq_locking_order_trunk/main/channel.c
team/dvossel/masq_locking_order_trunk/main/features.c
team/dvossel/masq_locking_order_trunk/main/pbx.c
Modified: team/dvossel/masq_locking_order_trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/masq_locking_order_trunk/channels/chan_sip.c?view=diff&rev=221392&r1=221391&r2=221392
==============================================================================
--- team/dvossel/masq_locking_order_trunk/channels/chan_sip.c (original)
+++ team/dvossel/masq_locking_order_trunk/channels/chan_sip.c Wed Sep 30 15:23:14 2009
@@ -19181,17 +19181,14 @@
}
ast_debug(4, "SIP Park: Transferer channel %s, Transferee %s\n", transferer->name, transferee->name);
- ast_channel_lock(transferee);
if (ast_do_masquerade(transferee)) {
ast_log(LOG_WARNING, "Masquerade failed.\n");
transmit_response(transferer->tech_pvt, "503 Internal error", &req);
- ast_channel_unlock(transferee);
if (d->req.data)
ast_free(d->req.data);
free(d);
return NULL;
}
- ast_channel_unlock(transferee);
res = ast_park_call(transferee, transferer, 0, &ext);
@@ -19290,15 +19287,12 @@
ast_copy_string(transferer->exten, chan2->exten, sizeof(transferer->exten));
transferer->priority = chan2->priority;
- ast_channel_lock(transferer);
if (ast_do_masquerade(transferer)) {
ast_log(LOG_WARNING, "Masquerade failed :(\n");
- ast_channel_unlock(transferer);
transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
ast_hangup(transferer);
return -1;
}
- ast_channel_unlock(transferer);
if (!transferer || !transferee) {
if (!transferer) {
ast_debug(1, "No transferer channel, giving up parking\n");
@@ -19734,10 +19728,13 @@
else
ast_debug(4, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name);
- /* C should now be in place of replacecall */
+ /* C should now be in place of replacecall. all channel locks should be removed before issuing the masq */
+ ast_channel_unlock(replacecall);
+ ast_channel_unlock(c);
if (ast_do_masquerade(replacecall)) {
ast_log(LOG_WARNING, "Failed to perform masquerade with INVITE replaces\n");
}
+ ast_channel_lock_both(replacecall, c);
if (earlyreplace || oneleggedreplace ) {
c->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
@@ -21589,6 +21586,7 @@
while (bridge && ast_channel_trylock(bridge)) {
ast_channel_unlock(p->owner);
do {
+ ast_channel_unlock(p->owner);
/* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */
sip_pvt_unlock(p);
usleep(1);
@@ -21662,7 +21660,9 @@
if (bridged_to) {
/* Don't actually hangup here... */
ast_queue_control(c, AST_CONTROL_UNHOLD);
+ ast_channel_unlock(c); /* async_goto can do a masquerade, no locks can be held during a masq */
ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1);
+ ast_channel_lock(c);
} else
ast_queue_hangup(p->owner);
}
Modified: team/dvossel/masq_locking_order_trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/masq_locking_order_trunk/main/channel.c?view=diff&rev=221392&r1=221391&r2=221392
==============================================================================
--- team/dvossel/masq_locking_order_trunk/main/channel.c (original)
+++ team/dvossel/masq_locking_order_trunk/main/channel.c Wed Sep 30 15:23:14 2009
@@ -2143,8 +2143,11 @@
ast_autoservice_stop(chan);
if (chan->masq) {
- if (ast_do_masquerade(chan))
+ ast_channel_unlock(chan);
+ if (ast_do_masquerade(chan)) {
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
+ }
+ ast_channel_lock(chan);
}
if (chan->masq) {
@@ -2514,13 +2517,13 @@
/* Perform any pending masquerades */
for (x = 0; x < n; x++) {
- ast_channel_lock(c[x]);
if (c[x]->masq && ast_do_masquerade(c[x])) {
ast_log(LOG_WARNING, "Masquerade failed\n");
*ms = -1;
- ast_channel_unlock(c[x]);
return NULL;
}
+
+ ast_channel_lock(c[x]);
if (!ast_tvzero(c[x]->whentohangup)) {
if (ast_tvzero(whentohangup))
now = ast_tvnow();
@@ -2641,16 +2644,15 @@
struct ast_channel *winner = NULL;
struct ast_epoll_data *aed = NULL;
- ast_channel_lock(chan);
/* See if this channel needs to be masqueraded */
if (chan->masq && ast_do_masquerade(chan)) {
ast_log(LOG_WARNING, "Failed to perform masquerade on %s\n", chan->name);
*ms = -1;
- ast_channel_unlock(chan);
return NULL;
}
+ ast_channel_lock(chan);
/* Figure out their timeout */
if (!ast_tvzero(chan->whentohangup)) {
if ((diff = ast_tvdiff_ms(chan->whentohangup, ast_tvnow())) < 0) {
@@ -2726,13 +2728,13 @@
struct ast_channel *winner = NULL;
for (i = 0; i < n; i++) {
- ast_channel_lock(c[i]);
if (c[i]->masq && ast_do_masquerade(c[i])) {
ast_log(LOG_WARNING, "Masquerade failed\n");
*ms = -1;
- ast_channel_unlock(c[i]);
return NULL;
}
+
+ ast_channel_lock(c[i]);
if (!ast_tvzero(c[i]->whentohangup)) {
if (whentohangup == 0)
now = ast_tvnow();
@@ -3067,21 +3069,22 @@
int count = 0, cause = 0;
/* this function is very long so make sure there is only one return
- * point at the end (there are only two exceptions to this).
+ * point at the end (there are only three exceptions to this).
*/
+
+ if (chan->masq) {
+ if (ast_do_masquerade(chan))
+ ast_log(LOG_WARNING, "Failed to perform masquerade\n");
+ else
+ f = &ast_null_frame;
+ return f;
+ }
+
while(ast_channel_trylock(chan)) {
if(count++ > 10)
/*cannot goto done since the channel is not locked*/
return &ast_null_frame;
usleep(1);
- }
-
- if (chan->masq) {
- if (ast_do_masquerade(chan))
- ast_log(LOG_WARNING, "Failed to perform masquerade\n");
- else
- f = &ast_null_frame;
- goto done;
}
/* Stop if we're a zombie or need a soft hangup */
@@ -3893,9 +3896,13 @@
goto done;
/* Handle any pending masquerades */
- if (chan->masq && ast_do_masquerade(chan)) {
- ast_log(LOG_WARNING, "Failed to perform masquerade\n");
- goto done;
+ if (chan->masq) {
+ ast_channel_unlock(chan);
+ if (ast_do_masquerade(chan)) {
+ ast_log(LOG_WARNING, "Failed to perform masquerade\n");
+ return res; /* no need to goto done: chan is already unlocked for masq */
+ }
+ ast_channel_lock(chan);
}
if (chan->masqr) {
res = 0; /* XXX explain, why 0 ? */
@@ -5063,7 +5070,9 @@
/*!
\brief Masquerade a channel
- \note Assumes channel will be locked when called
+ \note Assumes _NO_ channels are locked. If a channel is locked while calling
+ this function, it invalidates our channel container locking order. All channels
+ must be unlocked before it is permissible to lock the channels' ao2 container.
*/
int ast_do_masquerade(struct ast_channel *original)
{
Modified: team/dvossel/masq_locking_order_trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/masq_locking_order_trunk/main/features.c?view=diff&rev=221392&r1=221391&r2=221392
==============================================================================
--- team/dvossel/masq_locking_order_trunk/main/features.c (original)
+++ team/dvossel/masq_locking_order_trunk/main/features.c Wed Sep 30 15:23:14 2009
@@ -4378,17 +4378,19 @@
static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
{
ast_moh_stop(chan);
- ast_channel_lock(chan);
+ ast_channel_lock_both(chan, tmpchan);
ast_setstate(tmpchan, chan->_state);
tmpchan->readformat = chan->readformat;
tmpchan->writeformat = chan->writeformat;
ast_channel_masquerade(tmpchan, chan);
- ast_channel_lock(tmpchan);
+ ast_channel_unlock(chan);
+ ast_channel_unlock(tmpchan);
+
+ /* must be done without any channel locks held */
ast_do_masquerade(tmpchan);
+
/* when returning from bridge, the channel will continue at the next priority */
ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
- ast_channel_unlock(tmpchan);
- ast_channel_unlock(chan);
}
/*!
@@ -5004,9 +5006,10 @@
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, args.dest_chan);
}
+
+ ast_channel_unlock(current_dest_chan);
+
do_bridge_masquerade(current_dest_chan, final_dest_chan);
-
- ast_channel_unlock(current_dest_chan);
/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
/* try to make compatible, send error if we fail */
Modified: team/dvossel/masq_locking_order_trunk/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/masq_locking_order_trunk/main/pbx.c?view=diff&rev=221392&r1=221391&r2=221392
==============================================================================
--- team/dvossel/masq_locking_order_trunk/main/pbx.c (original)
+++ team/dvossel/masq_locking_order_trunk/main/pbx.c Wed Sep 30 15:23:14 2009
@@ -7662,10 +7662,12 @@
tmpchan = NULL;
res = -1;
} else {
- /* Grab the locks and get going */
- ast_channel_lock(tmpchan);
+ /* it may appear odd to unlock chan here since the masquerade is on
+ * tmpchan, but no channel locks should be held when doing a masquerade
+ * since a masquerade requires a lock on the channels ao2 container. */
+ ast_channel_unlock(chan);
ast_do_masquerade(tmpchan);
- ast_channel_unlock(tmpchan);
+ ast_channel_lock(chan);
/* Start the PBX going on our stolen channel */
if (ast_pbx_start(tmpchan)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
More information about the asterisk-commits
mailing list