Using Cancel Handlers

Cancel handlers provide an important function by allowing you to get control for clean-up and recovery actions when call stack entries are terminated by something other than a normal return. For example, you might want one to get control when a procedure ends via a system request '2', or because an inquiry message was answered with 'C' (Cancel).

The Register Call Stack Entry Termination User Exit Procedure (CEERTX) and the Call Stack Entry Termination User Exit Procedure (CEEUTX) ILE bindable APIs provide a way of dynamically registering a user-defined routine to be run when the call stack entry for which it is registered is cancelled. Once registered, the cancel handler remains in effect until the call stack entry is removed, or until CEEUTX is called to disable it. For more information on these ILE bindable APIs, see the CL and APIs section of the Programming category in the System i Information Center at this Web site - http://www.ibm.com/systems/i/infocenter/.

Figure 145 shows an example of enabling and coding a cancel handler for a subprocedure. (Cancel handlers can also be enabled for cycle-main procedures in the same way.)

Figure 145. Enabling and Coding a Cancel Handler for a Subprocedure
      *-----------------------------------------------------------------
      * Define the prototype for the cancel handler.  This procedure is
      * a local procedure.
      *-----------------------------------------------------------------
     D CanHdlr         PR
     D   pMsg                          *
      *-----------------------------------------------------------------
      * Define the prototype for a subprocedure to enable the cancel
      * handler.
      *-----------------------------------------------------------------
     D Enabler         PR
      *-----------------------------------------------------------------
      * Define the prototype for a subprocedure to call Enabler
      *-----------------------------------------------------------------
     D SubProc         PR
      *-----------------------------------------------------------------
      * Main procedure.  Call SubProc three times.
      *-----------------------------------------------------------------
     C                   CALLP     SubProc
     C                   CALLP     SubProc
     C                   CALLP     SubProc
     C                   SETON                                          LR
      *-----------------------------------------------------------------
      * Procedure SubProc.  Call Enabler.  Since this call will fail,
      * define a local *PSSR subroutine to handle the error.
      *-----------------------------------------------------------------
     P SubProc         B
     C                   CALLP     Enabler
      *-----------------------------------------------------------------
      * The PSSR has a RETURN operation, so the call from the main
      * procedure to SubProc will not fail.
      *-----------------------------------------------------------------
     C     *PSSR         BEGSR
     C     'Subproc PSSR'DSPLY
     C                   RETURN
     C                   ENDSR
     P SubProc         E
      *-----------------------------------------------------------------
      * Procedure Enabler.  This procedure enables a cancel handler,
      * then gets an error which causes Enabler to be canceled.
      *-----------------------------------------------------------------
     P Enabler         B
      * Local variables
     D Handler         S               *   PROCPTR  INZ(%PADDR('CANHDLR'))
     D Msg             S             20A
     D pMsg            S               *   INZ(%ADDR(Msg))
     D Zero            S              5P 0 INZ(0)
     D Count           S              5I 0 INZ(0) STATIC
     D Array           S              1A   DIM(2)
      *-----------------------------------------------------------------
      * Enable the cancel handler.  When this procedure gets canceled,
      * procedure 'CANHDLR' will be called.
      *-----------------------------------------------------------------
     C                   CALLB     'CEERTX'
     C                   PARM                    Handler
     C                   PARM                    pMsg
     C                   PARM                    *OMIT
      *-----------------------------------------------------------------
      * This procedure will be called three times.  The first two times
      * will get an error while the cancel handler is enabled.
      *-----------------------------------------------------------------
     C                   EVAL      Count = Count + 1
     C                   SELECT
     C                   WHEN      Count = 1
     C                   EVAL      Msg = 'Divide by zero'
     C                   EVAL      Zero = Zero / Zero
     C                   WHEN      Count = 2
     C                   EVAL      Msg = 'String error'
     C     'A'           SCAN      'ABC':Zero    Zero
      *-----------------------------------------------------------------
      * On the third call, disable the cancel handler.  The array index
      * error will cause the procedure to fail, but the handler will
      * not be invoked.
      *-----------------------------------------------------------------
     C                   WHEN      Count = 3
     C                   CALLB     'CEEUTX'
     C                   PARM                    Handler
     C                   PARM                    *OMIT
     C                   EVAL      Msg = 'Array index error'
     C                   EVAL      Array(Zero) = 'x'
     C                   ENDSL
     P Enabler         E
      *-----------------------------------------------------------------
      * Define the cancel handler.  The parameter is a pointer to the
      * 'communication area', a message to be displayed.
      *-----------------------------------------------------------------
     P CanHdlr         B
     D CanHdlr         PI
     D   pMsg                          *
      *-----------------------------------------------------------------
      * Define a field based on the input pointer pMsg.
      *-----------------------------------------------------------------
     D Msg             S             20A         BASED(pMsg)
      *-----------------------------------------------------------------
      * Display the message set by the procedure that enabled the
      * handler.
      *-----------------------------------------------------------------
     C     'Cancel Hdlr 'DSPLY                   Msg
     P CanHdlr         E

The following is the output from program CANHDLR. Note that the *PSSR of the procedure SubProc is called three times but the cancel handler is only called twice because it was disabled before the third error.

Figure 146. Output from CANHDLR program
DSPLY  Cancel Hdlr     Divide by zero
DSPLY  Subproc PSSR
DSPLY  Cancel Hdlr     String error
DSPLY  Subproc PSSR
DSPLY  Subproc PSSR


[ Top of Page | Previous Page | Next Page | Contents | Index ]