]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Prevent possible race condition on dual redirect of channels in the same bridge.
authorAsterisk Autobuilder <asteriskteam@digium.com>
Mon, 22 Dec 2014 18:28:33 +0000 (18:28 +0000)
committerAsterisk Autobuilder <asteriskteam@digium.com>
Mon, 22 Dec 2014 18:28:33 +0000 (18:28 +0000)
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/certified/branches/13.1@430007 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/manager.c

index 31c541085f891a4f360ad729141c11b5aaf9d0a7..26a9d68a5f8f337fd511e3c16b930a10b1c6349d 100644 (file)
@@ -4527,6 +4527,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");
@@ -4611,16 +4613,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)) {
@@ -4638,12 +4644,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);