RPG ON-EXIT is housekeeping for sub-procedures

RPG ON-EXIT is a nice structured way of storing procedure house keeping and/or error catching.

The ON-EXIT opcode in RPG is used to define a section of code that runs whenever a subprocedure ends, whether it ends normally or abnormally. This is particularly useful for cleanup tasks, such as deallocating resources or handling errors.

So how does ON-EXIT work?

Here’s a brief overview of how it works:

  1. Placement: The ON-EXIT section is placed at the end of the subprocedure, after all other code.
  2. Execution: This section runs when the subprocedure ends, regardless of how it ends (normal completion, return statement, unhandled exception, or cancellation).
  3. Indicator: You can specify an indicator to determine if the subprocedure ended abnormally. If the subprocedure ends normally, the indicator is set to *OFF; if it ends abnormally, the indicator is set to *ON.

Example

dcl-proc myprocedure;
  dcl-pi *n;
  end-pi; 

  dcl-s success ind inz(*off);

  // subprocedure main code here
  // this is where all your application logic would go
  // if it fails at anytime it will jump straight to
  // the on-exit statement, but if it trots down through
  // all your code then the last thing you want to do is
  // to tell the program that everything was successful.
  
  success = *on;
  return;
  
  on-exit success;

    if success;
      // do *normal* program closure items - close files, etc
      callp close(myfiles);
    else;
      // handle abnormal end
   endif;

end-proc;

In this example, the ON-EXIT section ensures that the cleanup code runs regardless of how the subprocedure ends.

The ON-EXIT operation code begins the ON-EXIT section. 

The ON-EXIT section contains code that runs every time that the procedure ends, whether it ends normally or abnormally.

The ON-EXIT section runs under the following conditions:

  • The procedure reaches the end of the main part of the procedure.
  • The procedure reaches a RETURN operation.
  • The procedure ends with an unhandled exception.
  • The procedure is canceled, due to the end of the job or subsystem, or due to an exception message being sent to a procedure higher in the call stack.

By placing your clean-up code, such as deleting temporary files and deallocating heap storage, in the ON-EXIT section, you ensure that it is always run, even if your procedure ends with an unhandled exception, or if it is canceled.

Extended Factor 2 contains an optional indicator variable that indicates whether the procedure ended normally or abnormally. If the procedure returned normally, the indicator is set to *OFF. If the procedure ended with an unhandled exception or if the procedure was canceled for any other reason, the indicator is set to *ON.

The ON-EXIT section is coded at the end of the sub-procedure, following any subroutines.

All variables and files defined in the procedure are available in the ON-EXIT section.

ON-EXIT EXAMPLE

So, how about using ON-EXIT something like this:

**free
dcl-proc myproc;
dcl-pi *n ind;
  incomingParameter int(10);
end-pi;

dcl-s success ind inz(*off);

dcl-s monitorCommandFailed ind inz(*off);

Open fileName;

// do lots of subprocedure logic stuff
// this is where you might have lots of RPG logic

if something;
  calculate = some + things;
endif;

doStuff = things * widgets / shoeshize;
filename = crtTempFile();
incomingParameter += 1;

// we could also handle errors this way
monitor;
  doSomethingThatFailsAlot(incomingParameter);
on-error;
  monitorCommandFailed = *on;
  return;
endif;

success = *on;
return;

on-exit success;

if success;
  close fileName;
  dltTempFile (filename);
else;
  // we could handle any UNMONITORED tasks here
endif;

// "monitorCommandFailed" is set *ON then we can 
// also handle a specific situation where the sub-proc
// 'doSomethingThatFailsAlot' has failed
if monitorCommandFailed;
  // perhaps run a stored proc to report the issue
  // (this 'reportproblem' proc could be part of a *srvpgm)
  reportProblem();
endif;

Close fileName;

end-proc;

That’s only rough code but it should give you the idea…

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>