Quick start manual

Program control
12-5
Exit procedures
Exit procedures
Exit procedures ensure that specific actions—such as updating and closing files—are
carried out before a program terminates. The ExitProc pointer variable allows you to
“install” an exit procedure, so that it is always called as part of the program’s
termination—whether the termination is normal, forced by a call to Halt, or the result
of a runtime error. An exit procedure takes no parameters.
Note
It is recommended that you use finalization sections rather than exit procedures for
all exit behavior. (See “The finalization section” on page 3-5.) Exit procedures are
available only for executables. For shared objects (Linux) or .DLLs (Windows) you
can use a similar variable, DllProc, which is called when the library is loaded as well
as when it is unloaded. For packages, exit behavior must be implemented in a
finalization section. All exit procedures are called before execution of finalization
sections.
Units as well as programs can install exit procedures. A unit can install an exit
procedure as part of its initialization code, relying on the procedure to close files or
perform other clean-up tasks.
When implemented properly, an exit procedure is part of a chain of exit procedures.
The procedures are executed in reverse order of installation, ensuring that the exit
code of one unit isn’t executed before the exit code of any units that depend on it. To
keep the chain intact, you must save the current contents of ExitProc before pointing
it to the address of your own exit procedure. Also, the first statement in your exit
procedure must reinstall the saved value of ExitProc.
The following code shows a skeleton implementation of an exit procedure.
var
ExitSave: Pointer;
procedure MyExit;
begin
ExitProc := ExitSave; // always restore old vector first
ƒ
end;
begin
ExitSave := ExitProc;
ExitProc := @MyExit;
ƒ
end.
On entry, the code saves the contents of ExitProc in ExitSave, then installs the MyExit
procedure. When called as part of the termination process, the first thing MyExit does
is reinstall the previous exit procedure.
The termination routine in the runtime library keeps calling exit procedures until
ExitProc becomes nil. To avoid infinite loops, ExitProc is set to nil before every call, so
the next exit procedure is called only if the current exit procedure assigns an address
to ExitProc. If an error occurs in an exit procedure, it is not called again.