diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-02 23:47:16 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-02 23:47:16 +0000 |
commit | 8106d010a132c8cf64c7c57aee78fccbd2b63a8c (patch) | |
tree | 2971d63fae50781397aa54cc7ed66511eda62ab1 | |
parent | cbe2b42e89d6f5c40a80778d66ff28c541b70257 (diff) |
Merged revisions 256015 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
................
r256015 | russell | 2010-04-02 18:46:45 -0500 (Fri, 02 Apr 2010) | 16 lines
Merged revisions 256014 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r256014 | russell | 2010-04-02 18:45:56 -0500 (Fri, 02 Apr 2010) | 9 lines
Resolve a deadlock that occurs due to a pointless call to ast_bridged_channel()
(closes issue #16840)
Reported by: bzing2
Patches:
patch.txt uploaded by bzing2 (license 902)
issue_16840.rev1.diff uploaded by russell (license 2)
Tested by: bzing2, russell
........
................
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@256016 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_local.c | 32 |
1 files changed, 8 insertions, 24 deletions
diff --git a/channels/chan_local.c b/channels/chan_local.c index 94893ebd0..138ded848 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -252,7 +252,11 @@ static int local_answer(struct ast_channel *ast) return res; } -static void check_bridge(struct local_pvt *p, int isoutbound) +/*! + * \internal + * \note This function assumes that we're only called from the "outbound" local channel side + */ +static void check_bridge(struct local_pvt *p) { struct ast_channel_monitor *tmp; if (ast_test_flag(p, LOCAL_ALREADY_MASQED) || ast_test_flag(p, LOCAL_NO_OPTIMIZATION) || !p->chan || !p->owner || (p->chan->_bridge != ast_bridged_channel(p->chan))) @@ -263,7 +267,7 @@ static void check_bridge(struct local_pvt *p, int isoutbound) frames on the owner channel (because they would be transferred to the outbound channel during the masquerade) */ - if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel! Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) { + if (p->chan->_bridge /* Not ast_bridged_channel! Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) { /* Masquerade bridged channel into owner */ /* Lock everything we need, one by one, and give up if we can't get everything. Remember, we'll get another @@ -297,26 +301,6 @@ static void check_bridge(struct local_pvt *p, int isoutbound) ast_channel_unlock(p->chan->_bridge); } } - /* We only allow masquerading in one 'direction'... it's important to preserve the state - (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan) - when the local channels go away. - */ -#if 0 - } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && AST_LIST_EMPTY(&p->chan->readq)) { - /* Masquerade bridged channel into chan */ - if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) { - if (!ast_check_hangup(p->owner->_bridge)) { - if (!ast_mutex_trylock(&p->chan->lock)) { - if (!ast_check_hangup(p->chan)) { - ast_channel_masquerade(p->chan, p->owner->_bridge); - ast_set_flag(p, LOCAL_ALREADY_MASQED); - } - ast_mutex_unlock(&p->chan->lock); - } - } - ast_mutex_unlock(&(p->owner->_bridge)->lock); - } -#endif } } @@ -337,8 +321,8 @@ static int local_write(struct ast_channel *ast, struct ast_frame *f) /* Just queue for delivery to the other side */ ast_mutex_lock(&p->lock); isoutbound = IS_OUTBOUND(ast, p); - if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) - check_bridge(p, isoutbound); + if (isoutbound && f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) + check_bridge(p); if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) res = local_queue_frame(p, isoutbound, f, ast, 1); else { |