Lessons by Jon

Self-Quitting CGI

This lesson will teach you how to create a CGI application that will quit after a specified period of inactivity. While there are a number of ways to do this, the method I will show is generic enough to use with almost any script and allows you to do processing on shutdown (if you want to save application settings). The majority of this added code came from an example by C. Joe Holmes.

Script2.txt - A Self-Quitting CGI

Here is the entire script for this lesson. The comments have been removed so you see only the lines that actually get compiled. The full script, including comments and special characters, is in the archive with the name "Script2.txt".
property crlf : (ASCII character 13) & (ASCII character 10)
property http_10_header : "HTTP/1.0 200 OK" & crlf & "Server: MacHTTP" & crlf & Ā
	"MIME-Version: 1.0" & crlf & "Content-type: text/html" & crlf & crlf
property idletime : 300
property datestamp : 0

set datestamp to current date

on «event WWW½sdoc» path_args ¬
   given «class kfor»:http_search_args, ¬
      «class post»:post_args, «class meth»:method, ¬
      «class addr»:client_address, «class user»:username, ¬
      «class pass»:password, «class frmu»:from_user, ¬
      «class svnm»:server_name, «class svpt»:server_port, ¬
      «class scnm»:script_name, «class ctyp»:content_type
	
   set datestamp to current date
	
   set return_page to http_10_header ¬
      & "<HTML><HEAD><TITLE>Unprocessed Results</TITLE></HEAD>" ¬
      & "<BODY><H1>Unprocessed Results</H1>" & return ¬
      & "<H4>http_search_args</H4>" & return & http_search_args
   set return_page to return_page & return ¬
      & "<H4>post_args</H4>" & return & post_args & return ¬
      & "<H4>method</H4>" & return & method & return ¬
      & "<H4>client_address</H4>" & return & client_address & return
   set return_page to return_page & return ¬
      & "<H4>from_user</H4>" & return & from_user & return ¬
      & "<H4>server_name</H4>" & return & server_name & return ¬
      & "<H4>server_port</H4>" & return & server_port & return
   set return_page to return_page & return ¬
      & "<H4>script_name</H4>" & return & script_name & return ¬
      & "<H4>content_type</H4>" & return & content_type & return ¬
      & "<H4>username</H4>" & return & username & return ¬
      & "<H4>password</H4>" & return
   set return_page to return_page ¬
      & "<I>Results generated at: " & (current date) ¬
      & "</I>" & "</BODY></HTML>"
   return return_page
	
end «event WWW½sdoc»

on idle
   if (current date) > (datestamp + idletime) then
      quit
   end if
   return 5
end idle

on quit
   continue quit
end quit

Step By Step

Let's take a look at the additions to the script.
   property idletime : 300
   property datestamp : 0
These are two new properties that are used to control when the CGI will quit itself. idletime tells how long to allow the CGI to remain idle before quitting. It is measured in seconds, so the line above lets the CGI run 5 minutes before quitting. datestamp contains the last date that something happened. As you will see below, it is set at startup and at the start of each AppleEvent. It is important that these are properties, so their value persists between AppleEvents received.
   set datestamp to current date
This line gets the current date (which includes day and time) and stores it in the variable datestamp. This line is used twice; once at the very start and once inside the AppleEvent handler. By putting it outside the AppleEvent handler, it ensures that the CGI will quit as desired even if it was somehow launched without an AppleEvent. The line inside the AppleEvent handler ensures that it will be reset each time an AppleEvent is processed.
NOTE: Within the AppleEvent handler, the datestamp is set at the very start. For this reason, your idletime should include the amount of time it will typically take your CGI to process the information. As an example, if your script usually takes one minute to run and you set your idletime to "120" (two minutes), you will actually have only about one minute after the first AppleEvent is finished before the CGI application will quit (unless another AppleEvent is sent). You could also solve this problem by moving the "set" statement in the AppleEvent handler to the end of the script, but that would mean placing a separate "set" statement before every "return" statement, which would be much more unwieldy and more likely to cause errors.
on idle
   if (current date) > (datestamp + idletime) then
      quit
   end if
   return 5
end idle
This new handler is introduced to test whether it is time to quit or not. When "nothing" is happening (meaning, when no AppleEvents are sent to this CGI), an "idle" event is sent to the CGI. The idle handler checks the current time and compares it to the last set time to see if it has been long enough to quit yet. If so, then it calls the quit handler (see below). If not, then it returns a value that tells how long to wait before checking for idle again (you don't want to tie up the whole cpu checking to see if you're idle!).
on quit
   continue quit
end quit
This new handler allows you to do processing before quitting. This might be useful if you wanted to save some information about the current state, wanted to log when the CGI runs, or anything else you can think of. Logging could be very useful to get an idea of whether your idletime is set too high or too low for the use the CGI is getting. Currently all this does is tell the CGI to go ahead and quit.

Wrap It Up

There is no demonstration page for this script, since you wouldn't be able to see the effects anyway. The lines and handlers introduced here should be easy to paste into any existing AppleScripts that you may have to add this handy feature.

There is one caveat when working with scripts that are self-quitting. You want to be careful not to quit the script before you are done processing all of the AppleEvents that might be queued up. This is not a problem with regular CGI applications. With the new ability to do asynchronous processing of CGI applications, though, there is the possibility for this to be a problem. For that reason, make sure that idletime is long enough for the AppleEvent to be processed and another one that is waiting to be accepted.


[Go back to Tutorial Index]

Jon Wiederspan
Last Edited: November 26, 1994