KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Self-Quitting Background Processes
PRODUCT: 4D | VERSION: 13.0 | PLATFORM: Mac & Win
Published On: May 18, 2012

A background process is generally any process that persists at runtime but has not GUI. Persistence is usually achieved via a loop of some sort.

Since background processes never "end", it is important that they quit gracefully at database shutdown. Said another way, a poorly implemented background process can prevent database exit and cause other unintended side effects.

A common way to manage this is to use the shutdown Database Methods (On Exit, On Server Shutdown) to notify any background processes that it is time to quit. However this becomes problematic with components.

The source code of a component (the matrix database) does have Database Methods, but these are not executed when used as a component. The shutdown methods of the host database can be modified to deal with background processes from the component, but this couples the component to the host database and unnecessarily complicates the code.

There is a simple 4D behavior that can be exploited to create self-quitting background processes: when the database is shutting down, calls to process control commands (e.g. DELAY PROCESS) do nothing. For example:

DELAY PROCESS(Current process;60)


This code has no effect if the database is shutting down, there is no reasonably measurable delay (and certainly not a 1 second delay as requested). This behavior can be used to detect that the database is quitting by wrapping the process control command. Here is a wrapper for DELAY PROCESS:

C_LONGINT($1;$delay_l) // Optional, default is 1 second.

C_BOOLEAN($0;$timeToQuit_f)

C_LONGINT($start_l;$end_l;$totalms_l;$totalTicks_l)

If (Count parameters>0)
   $delay_l:=$1
Else
   $delay_l:=60
End if

$start_l:=Milliseconds
DELAY PROCESS(Current process;$delay_l)
$end_l:=Milliseconds

$totalms_l:=$end_l-$start_l
$totalTicks_l:=$totalms_l*0.06

If ($totalTicks_l<$delay_l)
    // Delay process is no longer working, most likely the database is quitting.
   $timeToQuit_f:=True
Else
   $timeToQuit_f:=False
End if


This method simply measures the time it takes to execute DELAY PROCESS and checks to see if that time is less than the requested delay. If the delay was too short, the calling process can detect that it is time to quit. In this way background processes in components can gracefully exit without impacting the host database code. Of course this same technique can be used for any background process, it is not limited to components.

Note: there is some risk of prematurely ending the process by artificially waking up the process (e.g. with DELAY PROCESS(...;0) or CALL PROCESS). Keep this in mind.