AGI script that runs in the background and doesn't block the dialplan

I want to have an AGI script run in the background so that it doesn’t block the dialplan. I know how to make a process fork a child to do the real work and have the parent return right away just fine. No help necessary there thanks. The question is more about how Asterisk handles this.

I would for example like an AGI script that is running in the background while the Asterisk continues to execute the dialplan (and has moved on from the AGI() command that started the background process) to be able to run the EXEC back into Asterisk to run commands.

Is this at all possible? I have this feeling that once the AGI() command returns, all communication (i.e. stdin and stdout) with the process that AGI() started is terminated.

Hrm. Interesting. AGI() seems to block, even if the script it runs’ parent exits right way, leaving the child to run perhaps for an extended time. AGI() doesn’t seem to return until the child is complete, regardless of what the parent does.

Look into using “fastAGI”. Asterisk will communicate with the already running fastAGI program through TCP/IP.

I’ve been looking. How do I enable fastAGI in Asterisk?

Or do I have to install some additional software to be my fastAGI server, listening on the agi://.../ socket?

Was really hoping not to complicate things even worse with yet some other piece of software.

You could use the Asterisk server as the fastAGI server. The fastAGI program will deal with “listening”.

You would have to use AMI, rather than AGI once the agi application wasn’t running.

Did you close standard input and output when you terminated the parent?

Think of a call as a passing train,
Agi is when you stop the train (the call) to do something,
Ami is when you communicate with the train (the call) over the electrical wires on top of the train without stopping it : here you connect to manager port and can send instructions and asterisk can also send you events (where the call is and what is happening at each moment).
Ari is when you shoot the driver of the train and take his seat.

So I would answer your question with another question : do you want to stop the train or not ? Do you really want to kill a professional train driver ?

FastAGI is still going to block execution of the dialplan.

AGI executes a separate process and communicates with the process using STDIN/STDOUT. You can execute multiple threads in an AGI so you could have 1 thread interact with Asterisk while other threads do other stuff.

FastAGI communicates with a separate process using TCP/IP. The process may be ‘long running’ and can be designed to handle multiple connections (like a web server) and it may run on the same host as Asterisk or a separate host.

FastAGI’s advantage (IMHO) is performance:

  1. It can communicate with an ‘already running’ process, skipping process creation and script parsing if you are not using a compiled language.
  2. It can maintain a connection to a database, skipping a time consuming (cough, cough, Oracle) step.
  3. It can move the ‘AGI processing load’ to another host so your Asterisk server can handle more calls!

In spite of the advantages, in almost 20 years, I’ve only used FastAGI once and that was on a project where they had already coded their monster application in Java. ‘Process based AGI’ is just so much ‘simpler’ :slight_smile: Yes, process creation is ‘expensive’ but if you are using a compiled language (I use C), you will be surprised how many AGIs you can execute per second.

Nobody has mentioned ‘agi:async.’ I’ve never used it, but it may be of interest.

Stepping back, what are you actually trying to accomplish? Maybe AGI is the wrong approach.

1 Like

You would have to use AMI, rather than AGI once the agi application wasn’t running.

Yes, this makes sense. Fortunately my AGI script is already using AMI to do some of it’s work.

Did you close standard input and output when you terminated the parent?

Ahh. That I probably didn’t do. But I would also expect, now that I have had time to think about it, once the AGI() returns, anything I send to it’s stdin from my AGI script’s stdout is probably ignored anyway, so the ability to have my script to close stdio and return the parent process while leaving the child in the background, continuing to try to communicate with the AGI() call is a dead effort.

The point about closing the file descriptors is that the AGI application may well look for that, rather than the top level process terminating, to detect when it should, itself, exit.

what are you actually trying to accomplish? Maybe AGI is the wrong approach.

I am trying to deal with mobile phones running SIP clients. The basic problem is that SIP clients on mobile phones are not quite like SIP clients on computers or hard-phones. SIP clients on mobile phones, like any app on a mobile phone are subject to the operating system judging the process as being unused and killing it. Of course when that happens, any SIP registration that SIP client had is dead.

So how does such a killed SIP client respond to an INVITE for example? Well, there is a concept on mobile O/Ses of being able to re-start a previously killed app called push notification. A message is sent from a server to a mobile phone telling it that it should start up a given app and give it a message, to which the app responds however it wants.

So in the case of a SIP client on a mobile device, the SIP server that wants to send it an INVITE first has to check if the client is still connected (i.e. has an open TCP socket for example). If it is, it can just send a SIP message (INVITE for example) as if it were a regular device. If there is no open socket though, then the mobile O/S has killed the client and now the SIP server has to send a push notification to the mobile device. The SIP server then has to wait for the client to be started (by the mobile O/S) and re-REGISTER so the SIP server. Once the registration has been done, the SIP server can send a SIP INVITE.

This process of sending a push to the point of being able to send an INVITE only takes a small number of seconds so it’s pretty workable. Assuming the device is on and willing to respond. But what if a user has turned their phone off? The SIP server ends up timing out waiting for a SIP REGISTER. No big deal. Such a device just doesn’t get an SIP INVITE and the caller is routed to the regular “no answer” path.

That’s how voice is covered. But SIP also allows for MESSAGE, which SIP servers and soft-clients can use to implement SMS. So the above process all works the same for MESSAGE as it does INVITE. If a mobile client has been killed, the SIP server has to wait for it to wake up and REGISTER before it can send the SIP MESSAGE, which again can happen within a small number of seconds, but can be longer or can even time out. Due to the non-realtime aspect of messaging, a SIP server might want to set a timeout for a soft-client to REGISTER for a MESSAGE to a relatively long time. Say 10, 30 or even 60 seconds to increase reliability.

This all still works fine, even with a long timeout, when the final target of the dialplan is to just send a MESSAGE and then end the call flow since having the diaplan sitting waiting possibly 10s of seconds to send the message doesn’t hold anything else up. The only thing it’s trying to do is send a message.

However! If you want to send a message to a mobile device in the middle of a dialplan operation that is expected to continue on and do other work, like maybe Dial() some extensions to bridge them to an incoming call, that delay in the AGI() command is disastrous to the process of bridging an incoming call to some extensions. This is where you want the process of sending the message to go off on it’s own and not hold up the dialplan while it does it’s work, effectively putting the message sending process in parallel with the process of bridging the incoming call to extensions, rather than being a serial and blocking process. In this case you want the AGI() to return immediately and have the process it started continue on in the background, finally sending the message once the mobile SIP client wakes up.

Since I am already using AMI in the AGI script to detect when the mobile SIP client has re-REGISTERED, it seems that the previously posted suggestion of using AMI to do the MessageSend() is the best solution.

Unless somebody else sees a completely different and better way to skin this cat.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.