[asterisk-bugs] [JIRA] (ASTERISK-25525) A call EndWhile can cause the dial plan to jump to another context.

Steven T. Wheeler (JIRA) noreply at issues.asterisk.org
Fri Nov 6 09:18:33 CST 2015


    [ https://issues.asterisk.org/jira/browse/ASTERISK-25525?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=228187#comment-228187 ] 

Steven T. Wheeler commented on ASTERISK-25525:
----------------------------------------------

These conditions severely limit the usefulness of while loops and significantly add to the complexity of using them. If I want to return from inside a loop that means I need to set a variable, check the variable, exit the loop, then check that variable again to see if I return or continue execution.

{code}
[my-subroutine]
exten => s,1,Set(i=0)
 same => n,While($[${INC(i)} <= 5])
 same => n,Set(return=$[some condition])
 same => n,ExecIf($[${return}]?ExitWhile)
 same => n,Noop; More loop logic ...
 same => n,EndWhile
 same => n,ExecIf($[${return}]?Return)
 same => n,Noop; More subroutine logic ...
 same => n,Return
{code}

This code is far less readable and takes it much longer to understand what is happening. Also, I am unclear on whether or not this would work if I wanted to exit the loop on the first iteration?

It would make a lot more sense for any application that changes the dialplan's execution stack to have the effect of ending the while loop. Or to have some loop identifier so that you can specify which While an EndWhile will return to.

> A call EndWhile can cause the dial plan to jump to another context.
> -------------------------------------------------------------------
>
>                 Key: ASTERISK-25525
>                 URL: https://issues.asterisk.org/jira/browse/ASTERISK-25525
>             Project: Asterisk
>          Issue Type: Bug
>      Security Level: None
>          Components: Applications/app_while, Documentation
>    Affects Versions: 11.6.0
>            Reporter: Steven T. Wheeler
>            Severity: Minor
>
> [Edit by Rusty - Adding a note here at the top for quick reference. The documentation is not sufficient currently. See Richard's comment]
> I would expect that a While/EndWhile loop would be restricted to a single context. However, in some cases a call EndWhile can cause the dial plan to jump to another context. We have noticed this with Gosub and Goto.
> Here is a simple example:
> {code:title=extensions.conf|borderStyle=solid}
> [test-while-out]
> exten => s,1,Set(i=0)
>  same => n,While($[${INC(i)} <= 5])
>   same => n,Log(NOTICE,i is ${i})
>   same => n,Gosub(test-while-inner,s,1)
>  same => n,EndWhile
> [test-while-inner]
> exten => s,1,Set(j=0)
>  same => n,While($[${INC(j)} <= 5])
>   same => n,Log(NOTICE,j is ${j})
>   same => n,Return
>  same => n,EndWhile
>  same => n,Return
> {code}
> And in the Asterisk console execute:
> {code:title=Console|borderStyle=solid}
> *CLI> originate Local/s at test-while-out application wait 10
>     -- Executing [s at test-while-out:1] Set("Local/s at test-while-out-00000008;2", "i=0") in new stack
>     -- Executing [s at test-while-out:2] While("Local/s at test-while-out-00000008;2", "1") in new stack
>     -- Executing [s at test-while-out:3] Log("Local/s at test-while-out-00000008;2", "NOTICE,i is 1") in new stack
> [2015-11-05 16:28:59] NOTICE[27770][C-00000013]: Ext. s:3 @ test-while-out: i is 1
>     -- Executing [s at test-while-out:4] Gosub("Local/s at test-while-out-00000008;2", "test-while-inner,s,1") in new stack
>     -- Executing [s at test-while-inner:1] Set("Local/s at test-while-out-00000008;2", "j=0") in new stack
>     -- Executing [s at test-while-inner:2] While("Local/s at test-while-out-00000008;2", "1") in new stack
>     -- Executing [s at test-while-inner:3] Log("Local/s at test-while-out-00000008;2", "NOTICE,j is 1") in new stack
> [2015-11-05 16:28:59] NOTICE[27770][C-00000013]: Ext. s:3 @ test-while-inner: j is 1
>     -- Executing [s at test-while-inner:4] Return("Local/s at test-while-out-00000008;2", "") in new stack
>     -- Executing [s at test-while-out:5] EndWhile("Local/s at test-while-out-00000008;2", "") in new stack
>     -- Executing [s at test-while-inner:2] While("Local/s at test-while-out-00000008;2", "1") in new stack
>     -- Executing [s at test-while-inner:3] Log("Local/s at test-while-out-00000008;2", "NOTICE,j is 2") in new stack
> [2015-11-05 16:28:59] NOTICE[27770][C-00000013]: Ext. s:3 @ test-while-inner: j is 2
>     -- Executing [s at test-while-inner:4] Return("Local/s at test-while-out-00000008;2", "") in new stack
> [2015-11-05 16:28:59] ERROR[27770][C-00000013]: app_stack.c:378 return_exec: Return without Gosub: stack is empty
>   == Spawn extension (test-while-inner, s, 4) exited non-zero on 'Local/s at test-while-out-00000008;2'
> {code}
> The call starts at test-while-out which contains a While/EndWhile loop. Inside that loop it logs the value of {{i}} and the Gosubs to test-while-inner. The inner context also contains a While/EndWhile loop but we return from inside the loop. In the real world this would be due to some conditional statement. After returning to the outer loop we call EndWhile. I would expect this to bring us back to the beginning of the outer loop. But it actually brings us back to the beginning of the inner loop.



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



More information about the asterisk-bugs mailing list