Summary:ASTERISK-05289: System() doesn't behave as expected when shell command returns non-zero
Reporter:kb1_kanobe2 (kb1_kanobe2)Labels:
Date Opened:2005-10-13 03:08:27Date Closed:2011-06-07 14:10:43
Versions:Frequency of
Environment:Attachments:( 0) 20051013__filestat.diff.txt
Description:I have a filesystem based IVR in use that contains a very large number of menu options and leaf recordings (see 'Implementing a high-density IVR without wearing out your keyboard ' at http://www.voip-info.org/wiki-Asterisk+tips+IVR+menu for detail). Part of the process relies on acting conditionally on the presence of a particular filename. The test is implemented using a system call, thus:

System(/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/${digitstack}?.gsm)

to a shell script, thus:


for a in $1;
if [ -f $a ] ; then
#       echo exists;
#       echo doesnt;
       exit 1;

Under CVS-HEAD 2005-08-10, everything works just fine:
   -- Executing System("Zap/1-1", "/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/011111?.gsm") in new stack
   -- Executing NoOp("Zap/1-1", "there arent any menus below this one, so go back up one level") in new stack

However, with CVS-HEAD 2005-10-13, if the script returns 1 the System() command hangs and eventually times out, thus:

   -- Executing System("Zap/1-1", "/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/011111?.gsm") in new stack
   -- Timeout on Zap/1-1

Returning 0 works just fine.

I can't see a good reason for this behaviour... any suggestions?


I know the use of +101 is depreciated and generally evil, but I was upgrading for other reasons. :-)
Comments:By: Tilghman Lesher (tilghman) 2005-10-13 12:21:13

Here's a function.  Use this, instead.

By: Kevin P. Fleming (kpfleming) 2005-10-13 16:22:40

First off, System() did not 'hang'... the dialplan continued executing. Please show me the lines of your dialplan that are executing this stuff... the application appears to be doing the right thing, which is to return to the next step in the dialplan.

By: kb1_kanobe2 (kb1_kanobe2) 2005-10-13 16:49:55

Sorry, it was late:

As you point out, and rereading the debug with fresh eyes, the timeout refers to a dialplan timeout, which leads me to think instead that system() isn't branching +101 on the non-zero result. Under the previous version of Asterisk everything functions correctly. Nothing else changed apart from the upgrade, however the ivr was written in late 2004 so there may be a structural incompatibility with something that's been going on with the depreciation of +101 behaviour.

There are two places in this context where the system() call occurs:

exten => s,1,NoOp(s,1 - Has ${digitstack} in the digitstack)
exten => s,2,GotoIf($[${LEN(${digitstack})} = 0]?s-restart,1)
exten => s,3,System(/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/${digitstack}.gsm)
exten => s,4,Background(transit-ivr/${digitstack})

which branches, +101, to:

exten => s,104,Background(transit-ivr/sorry-not-valid) ; Relative to s,3
exten => s,105,SetVar(digitstack=${digitstack:0:$[${LEN(${digitstack})} - 1]}) ; Pop most recent digit back off the stack
exten => s,106,Goto(s,1) ; And replay the previously valid path

or flows through to:

exten => s,9,System(/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/${digitstack}?.gsm)

which, upon timeout, falls through to:

exten => t,1,Goto(s,1) ; Replay the current path if they fail to respond...

or branches +101 to:

exten => s,110,NoOp(there aren't any menus below this one, so go back up one level) ; Relative to s,9
exten => s,111,SetVar(digitstack=${digitstack:0:$[${LEN(${digitstack})} - 1]}) ; Pop most recent digit back off the stack
exten => s,112,Goto(s,1) ; And replay the previously validpath

For the entire block of code for the IVR see the wiki article http://www.voip-info.org/wiki-Asterisk+tips+IVR+menu.

So, what change am I ignorant of?

By: Russell Bryant (russell) 2005-10-13 17:11:37

System appears to work fine for me ...

exit 1

exten => 3,1,System(/root/test)
exten => 3,2,NoOp(it works)  

*CLI> dial 3
   -- Executing System("OSS/dsp", "/root/test") in new stack
   -- Executing NoOp("OSS/dsp", "it works") in new stack

By: kb1_kanobe2 (kb1_kanobe2) 2005-10-13 17:37:25

Drumkilla, is that the expected behaviour?

I would have expected your demo to try to jump to +101 when 'exit 1' came back from shell and to continue on to 3,2,NoOp() when 'exit 0' is returned. Reading the verbiage for cmd system() on the wiki:

.... If the command itself executes but is in error, and if there exists a priority n + 101, where 'n' is the priority of the current instance, then the channel will be setup to continue at that priority level....

There is also documentation for trysystem() which seems to be more the behaviour you've shown, no?

By: Russell Bryant (russell) 2005-10-13 18:50:05

I have changed the 'show application system' docs in cvs head to reflect that the priority jumping only occurs when the option is globally enabled in extensions.conf.

By: Kevin P. Fleming (kpfleming) 2005-10-13 18:56:44

The logic in app_system is identical to what it was before... the jump occurs if the command result is non-zero.

However, in CVS HEAD, the jump only occurs if the global 'priorityjumping' option is enabled, but it's on by default. Do you have that option set in the general section of your extensions,conf?

I have just noticed that there is a bug in the config loader where the value will not reset to its default during a reload, but unless you were playing with that setting that won't be the cause of what you are seeing.

By: kb1_kanobe2 (kb1_kanobe2) 2005-10-13 19:07:34

Sorry, just reopening to follow up on Kevins question:

I don't have priorityjumping specified at all in my extensions.conf as it predates that new service, hence it defaulted to disabled. drumkilla pointed out the need to enable that option and tweaked the docs to give future befuddled people something to go on.

Thanks again.