diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-02 23:46:45 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-02 23:46:45 +0000 |
commit | 135b05634ce9cd6791825952c539cfa5b9d999e2 (patch) | |
tree | 894aa0d95832def92aeaa594ec05d510bd5b0a6e /channels | |
parent | 9fd7fd6fef2660735fdd33174afddb3629ca4bc8 (diff) |
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/trunk@256015 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-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 5de9ed5f3..b2c7b9ed4 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -292,7 +292,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))) @@ -303,7 +307,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 @@ -337,26 +341,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 } } @@ -377,8 +361,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 { |