Summary:ASTERISK-07349: TIMEOUT() values not respected inside Macro call from Dial() command
Reporter:Adam Long (worldlink)Labels:
Date Opened:2006-07-17 14:47:25Date Closed:2006-09-06 12:18:22
Versions:Frequency of
Environment:Attachments:( 0) app.c.patch
Description:A Macro defined like the example one below does not work as expected when called from within a Dial() command as follows ...  Dial(SIP/someuser,20,M(timeout-test));  It does however work fine when called directly from a regular extension via exten => 123,1,Macro(timeout-test);

exten => s,1,Set(TIMEOUT(response)=2);
exten => s,n,Set(TIMEOUT(digit)=1);
exten => s,n,Playback(welcome);
exten => s,n,Read(option,enter-phone-number10,10,,2);
exten => s,n,Playback(thank-you-for-calling);
exten => s,n,Playback(goodbye);

I understand these timeouts are obsurd for what this code is asking of the user. This is simply to demonstrate this bug.

If you execute this macro by calling the Macro() function direct the specified timeout values will be respected.  However when called from the Dial() command the default response timeout of 10 seconds and the digit timeout of 5 seconds is used, ignoring your specified timeouts.  I've also tried setting the Timeout values in the calling context before the Macro or Dial command and that did not effect the outcome either.

I'm not quite sure if this is by design or not.  It presents a problem
either way.

The reason i tripped across this was i use many Read() statements as follows in my dialout macros since i cannot use any extensions other than "s" in a macro along with WaitExten();

* Note this is of course AEL2 code below...  the 0.1 timeouts used to play the audio prompts waiting for response immediately one after the other with no delay.

   if ( ${LEN(${option})} = 0 )

   if ( ${LEN(${option})} = 0 )
   if ( ${LEN(${option})} = 0 )

   if ( ${LEN(${option})} = 0 )
   if ( ${LEN(${option})} = 0 )

   if ( ${LEN(${option})} = 0 )
   if ( ${LEN(${option})} = 0 )

Comments:By: Serge Vecher (serge-v) 2006-09-01 14:24:53

murf: another one for ya

By: Adam Long (worldlink) 2006-09-01 16:49:52

Hi Murf...

Just noticed you were assigned this...  let me know if you need anything else from me.   I just recently upgraded to 1.2.11 and problem still exists.

For the time being i have solved my problems using the patch i uploaded here.  

For now i'm just changing the default 6 second timeout for ast_app_getdata in apps.c to 1ms.

However, i think this might be more of a feature request than a bug...
The following code in app_read.c

if(timeout) {
to = atoi(timeout);
if (to <= 0)
to = 0;
to *= 1000;

It would appear that me supplying "0.1" to the asterisk Read() application as a timeout might be the issue.  It looks as though Read's smallest timeout can only be 1 second.

Am i reading that code right?

Not sure what  atoi(0.1)  would equate to.
What's confusing me is if atoi(0.1) equates to 1 then the timeout should be 1000ms or 1 second.  But ast_app_getdata waits 6 seconds (the default).  


By: Adam Long (worldlink) 2006-09-01 16:53:52

What's also very strange is the behavior is different depending on by which means the macro was called.  It's almost as if when called through the Dial() app as M(timeout-test) the TIMEOUT() variable settings are ignored.

Regardless of all what was mentioned above.

By: Steve Murphy (murf) 2006-09-05 11:35:57


Before we start traveling far down this road, let me verify that we are both thinking the same things. I can explain the difference in behavior in the side-affects of your macro, from running straight from the dialplan, to running under dial, in that Dial() is working to set up a bridge between two channels. One channel is the incoming call that is being processed, and the other is the outgoing call (to an extension, whatever). The macro is being called on the "called", or "outgoing" channel. Any channel variables the macro sets will be on the "outgoing", or called channel. So, you are expecting the digit timeouts to be honored at the called end, right?

By: Adam Long (worldlink) 2006-09-05 13:09:24

Hi Murf,

That is correct, I needed the timeout values to be respected in the outgoing channel.  The macro would be used to present the dial'ed "callee" ,so to speak, with a series of prompts.


By: Steve Murphy (murf) 2006-09-06 00:44:24

OK, I can repeat your results; but I still have to find a few missing puzzle peices before I can make a good decision.

First of all, the Read() app only uses the TIMEOUT(response) if the optional argument for timeout is not supplied. In your example code, you do not supply a value.

Next, for some reason (a peice I'll have to find) the channel pbx structure is null, and that is where the TIMEOUT info is stored (rtimeout and dtimeout). Because of this, the TIMEOUT func does not actually do anything, and the Read app, supplied with neither the optional timeout arg, nor the channel variable value, defaults to 6 seconds. The only func that sets this ast_pbx_run(), and it is called for the incoming channel by dial, but not for the peer channel. Something tells that it is designed this way; if ast_pbx_run() were called on the peer (outgoing) channel, you wouldn't be able to run your macro on that channel. We'll see.  According to file, if we fired up ast_pbx_run on the peer channel in Dial(), your pbx would burst into flames, and weird things would happen! ;^)... But on a more serious note, calling a macro will not inherently need the services offered by ast_pbx_run(). When you hit the end of the "s" extension in the macro, it is an automatic return. No waiting for digits, etc.

Next, yes, the minimum (from my reading of the code) value for a timeout you can set in Read is 1 second. But, on the other hand, the documentation describes the timeout value in seconds.

Next, you can get past the TIMEOUT(response) not being settable, by simply providing one more argument to the Read app, the value "1", and you won't have to set the channel variables at all.

Next, the command to set the TIMEOUT(digit)  value is useless. Read does not use it. I will study who/why the pbx struct is filled in for chan by Dial, but not for peer.

By: Adam Long (worldlink) 2006-09-06 01:51:20

Hi Murf,

Your findings are right in line with what i was thinking after really tracing the code back.  

I suspected that pbx struct was null thus causing the results we see.
However, i just wasn't sure as to why.

I sure wouldn't want the PBX to melt down in flames ;-)

I would think that a channel struct being assigned to the peer channel might be useful.  CDR's for instance.  User A Dials into to exten 1 that in turn calls Dial(SIP/userb) you would think that should infact record two CDR entries.  Just a thought.

That actually lead me to think of something... I'm going to try creating a Local context that essentially act's as a proxy to the peer channel..
I use this frequently to get around the single CDR leg issue described above.

context macro-dialout {
   someuser => Dial(SIP/${EXTEN});

And then call the macro as follows...

or perhaps...


I'll let you know my results...

Thanks for your help on this.

By: Steve Murphy (murf) 2006-09-06 09:29:21

Uh, have you modified your app_read.c to accept floating point args for the delay? Because calling atoi() on 0.1 will just return the int 0 in the app_read code, which will result in the default (6 sec) timeout instead, especially in the dial macro.

By: Steve Murphy (murf) 2006-09-06 12:18:21

I've committed some fixes to the doc strings for app_dial and app_read, to reduce confusion over the issues brought up by this bug. v 42111. Also, added an item to a project list, for 1.6, to go thru the apps and make all timeouts floating point and in seconds units... someday.