[asterisk-bugs] [JIRA] (ASTERISK-26469) Infinite loop after a dual Redirect

Etienne Allovon (JIRA) noreply at issues.asterisk.org
Fri Oct 14 09:18:01 CDT 2016


Etienne Allovon created ASTERISK-26469:
------------------------------------------

             Summary: Infinite loop after a dual Redirect
                 Key: ASTERISK-26469
                 URL: https://issues.asterisk.org/jira/browse/ASTERISK-26469
             Project: Asterisk
          Issue Type: Bug
      Security Level: None
          Components: Bridges/bridge_simple
    Affects Versions: 13.11.2
         Environment: Debian 8.1
            Reporter: Etienne Allovon


*Summary :*

Given I have two channels bridged together by asterisk.
Gvien I send an AMI commend Redirect (with channel and extra_channel set)
Then an asterisk thread may end up using 100% cpu. One of the channel thread is stuck in the while loop at the end of {{bridge_channel_internal_join()}} where it waits for the flag {{AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT}} to be cleared.

*More details :*

The problem occurs when sending an ami command to redirect two bridged channels to another extension (Redirect with channel and extra_channel set). During the process, one of the channel thread is stuck in the while loop at the end of {{bridge_channel_internal_join()}} where it waits for the flag {{AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT}} to be cleared:
{code}
    /*
     * Wait for any dual redirect to complete.
     *
     * Must be done while "still in the bridge" for ast_async_goto()
     * to work right.
     */
    while (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT)) {
        sched_yield();
    }
{code}

The other channel thread seems to complete successfully.

One possible source of the problem lies in {{bridge_channel_internal_pull()}} which clears the flag {{AST_FLAG_OUTGOING}} without locking the channel first:
{code}
    /* If we are not going to be hung up after leaving a bridge, and we were an
     * outgoing channel, clear the outgoing flag.
     */
    if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_OUTGOING)
        && (ast_channel_is_leaving_bridge(bridge_channel->chan)
            || bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT)) {
        ast_debug(2, "Channel %s will survive this bridge; clearing outgoing (dialed) flag\n", ast_channel_name(bridge_channel->chan));
        ast_clear_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_OUTGOING);
    }
{code}
When in the manager thread, the {{action_redirect()}} clears the {{AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT}}:
{code}
    /* Release the bridge wait. */
    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 (chan2_wait) {
        ast_channel_lock(chan2);
        ast_clear_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
        ast_channel_unlock(chan2);
    }
{code}

So maybe the {{ast_clear_flag}} done inside the {{action_redirect()}} from the manager thread is overwritten by this call to {{ast_clear_flags}} in {{bridge_channel_internal_pull()}}



--
This message was sent by Atlassian JIRA
(v6.2#6252)



More information about the asterisk-bugs mailing list