Post-hangup processing in VoiceXML 2.x

During normal execution of a voice application, the user may decide to terminate her session by hanging up the phone. Voice application developers may be required to detect when the hangup occurs to perform additional processing such as the following:

  • To log usage statistics including the duration of the call and the call state when the user hung up
  • To perform server-side cleanup such as rolling back a database transaction

This article explains the recommended procedure for performing post-hangup processing on the Tellme Voice Application Network.

The Tellme voice application network services thousands of users concurrently. To ensure the most efficient use of network resources, once the user hangs up or is disconnected, the network provides the voice application the opportunity to perform five seconds of additional processing. While this restriction is not enforced today, Tellme Networks reserves the right to do so in the future. For that reason, it is critical that you follow these guidelines:

When a user hangs up or is disconnected, the Tellme VoiceXML interpreter throws the connection.disconnect.hangup event. To ensure the broadest range of coverage for this event, catch it within your application root document.

Note. Prior to Revision 1, the interpreter threw events in the 'telephone' namespace. In revision 1, the interpreter throws events in the 'connection' namespace. If you have an existing application running on the Tellme Voice Application Network, you are encouraged to upgrade it to the latest Tellme Revision. For a list of available revisions, see Tellme Revisions.

Note. If your application makes calls to subdialogs, be aware that, as an encapsulated block of code, a subdialog is typically defined in a separate VoiceXML document that does not set its application root to the same VoiceXML document as its caller. A robustly-designed subdialog should catch the connection.disconnect.hangup event and return the event to the caller.

When your voice application catches the connection.disconnect.hangup, use the submit element to submit a notification regarding the hangup to your server-side infrastructure. Set the fetchtimeout attribute to five seconds (5s).

The following code snippet submits the name of the dialog that was executing when the hangup occurred as well as the user's registration identifier. These variables are defined and maintained by the application; they are not built into the VoiceXML interpreter.

<catch event="connection.disconnect.hangup">
   <submit namelist="last_state usr_id" next="onhangup.cgi" fetchtimeout="5s" />

The code you author and run on your application server will vary depending upon your chosen application server framework and programming language, but the universal goal is to return control to the VoiceXML interpreter as quickly as possible so that it may terminate the session and service the next incoming request.

If you're using Perl within a CGI script, the simplest solution is to call the system function from your CGI script to spawn a new process. This has has some security implications, so take the following precautions:

  • Enable taint checking by setting the -T flag at the top of your CGI script
  • Eliminate semi-colons from the data you forward to the alternate process.
# /usr/local/bin/perl

my $qstr = ($ENV{QUERY_STRING} || ""); # grab data submitted to server from VoiceXML app
$qstr =~ s/;/ /g; # replace semi-colons to foil nefarious hackers
$qstr =~ s/&/ /g; # replace ampersands so they're not interpreted as "background this"
my $cmd = "perl -T $qstr &"; # append ampersand to execute 
                                     # process in the background (UNIX only)
system ($cmd); # execute the secondary script

PrintMinimalVoiceXML(); # return minimal VoiceXML to the client; described below

The secondary script,, runs in a separate background process, so the primary script returns immediately. The secondary script does not have access to the CGI environment, but the query string is the only data to which the secondary script needs access, and it is passed as a set of arguments accessible via the global array @ARGV.

The following example, also written in Perl, accepts the incoming submission from the VoiceXML interpreter and uses the fork function to spawn a child process to do the cleanup work while the main process sends a minimal amount of VoiceXML back the Tellme Voice Browser.

# /usr/local/bin/perl

my $pid;
unless ($pid = fork) # fork once
   unless (fork) # fork again!

      # your cleanup code goes here


PrintMinimalVoiceXML(); # send minimal VoiceXML to client

# send the minimal VoiceXML to stdout
sub PrintMinimalVoiceXML
   print "Content-type: text/xml\n\n";
   print <<EOF;
   <vxml version="2.1">

Note. The fork function may not be supported on all operating systems.

Another option, for simple logging purposes is to use a connectionless protocol such as e-mail to forward the data for further processing. The following example use Perl to send mail to a fictitious e-mail address, ""

my $qstr = $ENV{QUERY_STRING}; # log the query string
my $time = gmtime(); # log the current date/time in GMT
my $appname = "My App";
my $addr_from = "$appname\";
my $addr_to = "vproc\";

# create the message header/body
my $msg = qq{
From: $appname <$addr_from>
To: post-hangup processor <$addr_to>
Subject: $appname usage stat


SendMail($msg); # send the message
PrintMinimalVoiceXML(); # return minimal VoiceXML

# send a message using sendmail
sub SendMail ( $ ) {
    my ($msg) = @_;

    open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq")
	or die "Can't fork for sendmail: $!\n";

    print SENDMAIL $msg;
    close(SENDMAIL)     or warn "sendmail didn't close nicely";
    return 0;

The VoiceXML that you return from your HTTP server should be the minimum required to complete the submit. Tellme recommends the following:

<vxml version="2.1">

[24]7 Inc.| Terms of Service| Privacy Policy| General Disclaimers