Background Jobs

Many applications make use of some kind of background jobs, which leads to the question of how to implement them under A-Shell. UNDER AMOS, you would typically have launched such jobs from the system INI when the system was booted, but under A-Shell/Windows/UNIX there are a variety of possibilities and considerations, which are discussed below.

Launch background job when the system boots

Start by coming up with the necessary command line which will start A-Shell and then the program (typically via a startup command file). You can test that from the shell prompt (under UNIX) or from the Start>Run prompt under Windows. Once you have it perfected in interactive mode, to make it invisible, for Windows, add the -z (invisible) or perhaps -zi (system tray) switch to get it off the Task Bar; for UNIX, add code to the end of the command line to redirect the output, i.e. ">out.lst 2>1" (to redirect both stdout and stderr to the file out.lst) or "&gt/dev/null 2>err.lst" (to discard stdout but capture stderr). Under UNIX, you'll probably want to add "-td dumb" to set the terminal driver to "dumb" to eliminate emulation escape sequences from any captured output.

Finally to launch your command at system startup, for Windows create a shortcut with the command line and add it to the Startup folder. For UNIX, add it to rc.local (or the equivalent).

Job dies and needs to be re-launched

The first thing your background application should do is check to see if it is already running. One simple way to do this is to use the -j <jobname> switch to force it to use a specific job name. If the job name already exists, the A-Shell launch will fail, so there would be no harm in just re-launching it as often as you like, either manually or automatically. (This assumes that if the job dies, it will close itself down entirely. You can help guarantee that by using the -e startup switch, adding HOST to the end of the command file which starts the app, adding XCALL MIAMEX, MX_EXIT to your error trap, etc.)

Under Windows you can use the System Scheduler (aka "Scheduled Tasks") to force your shortcut to be launched every few minutes, so that if the background job does die, it will automatically get restarted. Same idea under UNIX, except using crontab.

Another possibility is that other jobs in your application can act as watchdogs, such that if they detect the background job is missing, they can relaunch it using XCALL HOSTEX, or, for UNIX, you might prefer XCALL SUBMIT (but use the /NEXT:0-0-0 option to make it run under control of the atd daemon rather than as a child of the job which launched it.)

Detect new version and re-launch

You can use XCALL GETVER to get the version of the currently running program. You can also use MIAMEX,107 to get the version of a program that has been loaded into memory.

To get the version of the program on disk, you could use DIR/V as you suggest, but it would be more efficient to read it directly from the file. Here's how DIR.LIT does it:

map1 STRING'VERSION,s,13        ! Version string

map1 VERSION                    ! Version no.

   map2 VMAJOR,f,6             ! Major version

   map2 VMINOR,f,6             ! Minor version

   map2 VSUB,f,6               ! Sub version

   map2 VEDIT,f,6              ! Edit number

   map2 VWHO,f,6               ! Patch level

map1 VRECORD                    ! version record

   map2 VBINARY(8),b,1         ! Individual bytes

map1 VRETURN,f,6                ! No. bytes actually read

 

MAKE'VERSION:

   STRING'VERSION = ""

   open #1,FILE$,input

   xcall GET,VRECORD,1,8,VRETURN

   if VRETURN = 8 and  VBINARY(1) >= 254 and VBINARY(2) = 255 then

      VMAJOR = VBINARY(4)

      VMINOR = VBINARY(3) and 15

      VSUB = int(VBINARY(6)/16)

      VEDIT = (VBINARY(6) and 15)*256+VBINARY(5)

      VWHO = int(VBINARY(3)/16)

      STRING'VERSION = str(VMAJOR)+"."+str(VMINOR)

      if VSUB then STRING'VERSION = STRING'VERSION+chr(64+VSUB)

      if VEDIT then STRING'VERSION = STRING'VERSION+"("+str(VEDIT)+")"

      if VWHO then STRING'VERSION = STRING'VERSION+"-"+str(VWHO)

   endif

   close #1

   return

 

Actually, there is a function in SOSFUNC: to extract the version from a RUN, LIT, or SBX file on disk: Fn'ProgVer$(progspec$)

Note that while you could install a new RUN while the program is running, XCALL GETVER will continue to get the version of the program running in memory, ignoring the updated one on disk. But Fn'ProgVer$() (or the raw code from DIR shown above) will read the version from the disk file, ignoring the one in memory. So by comparing the two periodically, you could detect when the version had been updated.

Node count and licensing

Do background jobs count as nodes against the license? Yes and no. The first background job does count. Additional jobs do not count until you have as many background jobs as you have licensed nodes, and then they start counting.

Keeping track of what background jobs are doing

The time-tested approach is for your background job to maintain a log file and/or status file that you can examine. You may find the SOSPROC: procedure SysLog() to be helpful. Also, keep in mind that if you want to be able to see the latest messages output to a sequential file, you either need to close it after each message (reopening for APPEND prior to each new message) or disable output buffering using MX_NOBUF. You'll also want to make sure when you query the log file that you don't open it in a way that will interfere with the on-going output to it.

Under Windows, if you run your background jobs from the system tray, you'll be able to make them visible by double-clicking on their icons in the system tray. (Although in a multi-user system, you'll have to do this from the PC which launched the job.)

Note: This topic was originally written as a post on our support forum. You might want to check the original post to see if there have been any additional comments: "Background Job (tips)"