In this final installment, we wrap things up with some related information you should know before employing clean-up procedures in your applications.
Seven must-know facts about clean-up procedures and the APIs
1. You can register multiple clean-up procedures for the same call stack entry or activation group.
2. Procedures registered with the CEERTX API are called in first-in-first-out (FIFO) order.
3. Procedures registered with the CEE4RAGE API are called in last-in-first-out (LIFO) order.
4. If a clean-up procedure fails, all subsequent (i.e., yet to be called) clean-up procedures for that same call stack entry or activation group are not called.
5. A clean-up procedure can be located in another activation group (e.g., if the cleanup procedure is part of a service program that runs in its own activation group), but it must be available when the system calls it or an exception will be signaled (i.e., the program or service program that contains it must still be activated). A procedure may not be available because, for example, the activation group that once contained it has been deleted.
6. A CL program can register a clean-up procedure, but you will have to use a helper procedure to get a pointer to the clean-up procedure that the APIs require (since CL does not directly support pointers, although in V5R4 CL does support data pointers).
7. You cannot set up a cleanup procedure for the default activation group (i.e., you cannot call the CEERTX or CEE4RAGE APIs from within the default activation group).
Ending activation groups
Activation groups are created automatically as needed. When a program is called, the system checks if its activation group (the one in which it will run) is already active. If not, the activation group is created.
How an activation group is ended (or deleted) is dependent on the type of activation group it is. A named activation group (a.k.a. a user-named activation group) can be ended by one of the following three methods:
1. A program running in the activation groups executes an exit operation (see below).
2. An unhandled condition is promoted past the activation group's hard control boundary. That is, an exception message is sent from the oldest call stack entry in the activation group (usually the first program called in the activation group) to its caller.
3. The RCLACTGRP (Reclaim Activation Group) command is used to explicitly delete the activation group.
A *NEW activation group (a.k.a. a system-named activation group) remains active as long as one or more of its programs/procedures are on the call stack. But, as soon as its last procedure is taken off the call stack for any reason (e.g., returning to its caller), the activation group is deleted. This means that a normal return operation, in addition to the methods described for named activation groups, will end a *NEW activation group. Note that, since the RCLACTGRP command can only be used to delete activation groups which are not in use (i.e., do not have entries on the call stack), it is impossible to use the RCLACTGRP command against a *NEW activation group because a *NEW activation group is deleted as soon as its last entry on the call stack is removed.
What is an exit operation?
An exit operation performs a normal end of the activation group in which it is executed. Any suspended entries on the call stack associated with the activation group are removed without regaining control. However, any clean-up procedures associated with the call stack entries are given control before the activation group ends.
C and COBOL have inherent exit operations. You use the exit() function in C and the STOP RUN statement in COBOL. RPG and CL do not have inherent exit operations. Setting-on the LR indicator in RPG or specifying the ENDPGM command in CL are not exit operations. To implement the exit operation in RPG or CL, you must use the CEETREC (Normal End of Activation Group) API. Tech note: In actuality, the C and COBOL exit operations call the CEETREC API.
The CEETREC API accepts two parameters, both are four-byte binary return codes. However, since both parameters are omissible, to perform a generic exit, simply call the CEETREC API omitting both parameters.
About the author: Ron Turull is editor of Inside Version 5. He has more than 20 years' experience programming for and managing AS/400-iSeries systems.
This was first published in July 2006