From 2b1f2b5c1f038ad6f470b2d0cc6569bdeb7923b6 Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Thu, 18 Dec 2014 15:18:45 +0000 Subject: Prevent possible race condition on dual redirect of channels in the same bridge. The AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT flag was created to prevent bridges from prematurely acting on orphaned channels in bridges. The problem with the AMI redirect action was that it was setting this flag on channels based on the presence of a PBX, not whether the channel was in a bridge. Whether a channel has a PBX is irrelevant, so the condition has been altered to check if the channel is in a bridge. ASTERISK-24536 #close Reported by Niklas Larsson Review: https://reviewboard.asterisk.org/r/4268 ........ Merged revisions 429741 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@429745 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/manager.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'main/manager.c') diff --git a/main/manager.c b/main/manager.c index a4ad0563d..05ef9a4d2 100644 --- a/main/manager.c +++ b/main/manager.c @@ -4545,6 +4545,8 @@ static int action_redirect(struct mansession *s, const struct message *m) int pi = 0; int pi2 = 0; int res; + int chan1_wait = 0; + int chan2_wait = 0; if (ast_strlen_zero(name)) { astman_send_error(s, m, "Channel not specified"); @@ -4629,16 +4631,20 @@ static int action_redirect(struct mansession *s, const struct message *m) } /* Dual channel redirect in progress. */ - if (ast_channel_pbx(chan)) { - ast_channel_lock(chan); + ast_channel_lock(chan); + if (ast_channel_is_bridged(chan)) { ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); - ast_channel_unlock(chan); + chan1_wait = 1; } - if (ast_channel_pbx(chan2)) { - ast_channel_lock(chan2); + ast_channel_unlock(chan); + + ast_channel_lock(chan2); + if (ast_channel_is_bridged(chan2)) { ast_set_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); - ast_channel_unlock(chan2); + chan2_wait = 1; } + ast_channel_unlock(chan2); + res = ast_async_goto(chan, context, exten, pi); if (!res) { if (!ast_strlen_zero(context2)) { @@ -4656,12 +4662,12 @@ static int action_redirect(struct mansession *s, const struct message *m) } /* Release the bridge wait. */ - if (ast_channel_pbx(chan)) { + if (chan1_wait) { ast_channel_lock(chan); ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); ast_channel_unlock(chan); } - if (ast_channel_pbx(chan2)) { + if (chan2_wait) { ast_channel_lock(chan2); ast_clear_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); ast_channel_unlock(chan2); -- cgit v1.2.3