CEEHDLR—Register user-written condition handler

CEEHDLR registers a user-written condition handler for the current stack frame. The user condition handler is invoked when:
  • It is registered for the current stack frame by CEEHDLR, and
  • The Language Environment condition manager requests the condition handler associated with the current stack frame handle the condition.

Language Environment places the user-written condition handlers associated with each stack frame in a queue. The queue can be empty at any given time. The Language Environment condition manager invokes the registered condition handlers in LIFO (last in, first out) order to handle the condition.

The opposite of CEEHDLR, which registers a user-written condition handler, is CEEHDLU, which unregisters the handler. You do not necessarily need to use CEEHDLU to remove user-written condition handlers you registered with CEEHDLR. Any user-written condition handlers created through CEEHDLR and not unregistered by CEEHDLU are unregistered automatically by Language Environment, but only when the associated stack frame is removed from the stack.

Language Environment condition handlers are driven only for synchronous conditions.
Read syntax diagramSkip visual syntax diagram
Syntax

>>-CEEHDLR--(--routine--,--token--,--fc--)---------------------><

routine (input)
An entry variable or entry constant for the routine called to process the condition. The entry variable or constant must be passed by reference. The routine must be an external routine; that is, it must not be a nested routine.
token (input)
A fullword integer of information you want passed to your user handler each time it is called. This can be a pointer or any other fullword integer you want to pass.
fc (output)
A 12-byte feedback code, optional in some languages, that indicates the result of this service. If you choose to omit this parameter, refer to Invoking callable services for the appropriate syntax to indicate that the feedback code was omitted.

The following symbolic conditions can result from this service:

Code Severity Message number Message text
CEE000 0 The service completed successfully.
CEE080 1 0256 The user-written condition handler routine specified was already registered for this stack frame. It was registered again.
CEE081 3 0257 The routine specified contained an invalid entry variable.

Usage notes

  • PL/I MTF consideration—CEEHDLR is not supported in PL/I MTF applications. This includes any CEEHDLR service called from a COBOL program in the application.
  • COBOL consideration—You should not call CEEHDLR from a nested COBOL program.
  • z/OS UNIX consideration—In multithread applications, CEEHDLR affects only the calling thread.
  • C consideration—The CEEHDLR service does not save Writeable Static Area (WSA) information about the user handler, so it's possible that the user handler will be given control with the wrong WSA. Specifically, the user handlers on the stack will be invoked with the WSA of the routine that incurred the condition. The preferred method of handling conditions from a C application is to use C signal handlers.

For more information

Examples

  1. Following is an example of CEEHDLR called by C/C++.
    /*Module/File Name: EDCHDLR   */
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <leawi.h>
    #include <ceeedcct.h>
    
    #ifdef __cplusplus
      extern "C" {
    #endif
      void handler(_FEEDBACK *,_INT4 *,_INT4 *,_FEEDBACK *);
    #ifdef __cplusplus
      }
    #endif
    
    int main(void) {
    
      _FEEDBACK fc;
      _ENTRY routine;
      _INT4 token;
    
      /* set the routine structure to point to the handler */
      /* and use CEEHDLR to register the user handler      */
    
      token = 99;
      routine.address = (_POINTER)&handler;
      routine.nesting = NULL;
    
      CEEHDLR(&routine,&token,&fc);
    
      /* verify that CEEHDLR was successful */
      if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
         printf("CEEHDLR failed with message number %d\n",
                fc.tok_msgno);
         exit (2999);
      }
     /*
     ⋮ 
    */
    }
    /*******************************************************/
    /* handler is a user condition handler                 */
    /*******************************************************/
    void handler(_FEEDBACK *fc, _INT4 *token, _INT4 *result,
                 _FEEDBACK *newfc) {
     /*
     ⋮
     */
    }
  2. Following is an example of CEEHDLR called by a COBOL program that registers a handler routine.
    CBL LIB,QUOTE
          *Module/File Name: IGZTHDLR
          ***********************************************
          **                                           **
          ** CBLHDLR - Call CEEHDLR to register a user **
          **           condition handler               **
          **                                           **
          ***********************************************
           IDENTIFICATION DIVISION.
           PROGRAM-ID. CBLHDLR.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01  ROUTINE  PROCEDURE-POINTER.
           01  TOKEN                   PIC S9(9) BINARY.
           01  SEV                     PIC S9(4) BINARY.
           01  MSGNO                   PIC S9(4) BINARY.
           01  CASE                    PIC S9(4) BINARY.
           01  SEV2                    PIC S9(4) BINARY.
           01  CNTRL                   PIC S9(4) BINARY.
           01  FACID                   PIC X(3).
           01  ISINFO                  PIC S9(9) BINARY.
           01  QDATA                   PIC S9(9) BINARY.
           01  FC.
               02  Condition-Token-Value.
               COPY  CEEIGZCT.
                   03  Case-1-Condition-ID.
                       04  Severity    PIC S9(4) BINARY.
                       04  Msg-No      PIC S9(4) BINARY.
                   03  Case-2-Condition-ID
                             REDEFINES Case-1-Condition-ID.
                       04  Class-Code  PIC S9(4) BINARY.
                       04  Cause-Code  PIC S9(4) BINARY.
                   03  Case-Sev-Ctl    PIC X.
                   03  Facility-ID     PIC XXX.
               02  I-S-Info            PIC S9(9) BINARY.
           01  CONDTOK.
               02  Condition-Token-Value.
               COPY  CEEIGZCT.
                   03  Case-1-Condition-ID.
                       04  Severity    PIC S9(4) BINARY.
                       04  Msg-No      PIC S9(4) BINARY.
                   03  Case-2-Condition-ID
                             REDEFINES Case-1-Condition-ID.
                       04  Class-Code  PIC S9(4) BINARY.
                       04  Cause-Code  PIC S9(4) BINARY.
                   03  Case-Sev-Ctl    PIC X.
                   03  Facility-ID     PIC XXX.
               02  I-S-Info            PIC S9(9) BINARY.
           PROCEDURE DIVISION.
           PARA-CBLHDLR.
               SET ROUTINE TO ENTRY "HANDLER".
               CALL "CEEHDLR" USING ROUTINE, TOKEN, FC.
               IF NOT CEE000 of FC  THEN
                   DISPLAY "CEEHDLR failed with msg "
                       Msg-No of FC UPON CONSOLE
                   STOP RUN
               END-IF.
          *  RAISE A SIGNAL
    
           PARA-CBLSGL.
          *************************************************
          ** Call CEENCOD with the values assigned above **
          ** to build a condition token "CONDTOK"        **
          ** Set CONDTOK to sev=3, msgno=1 facid=CEE. We **
          ** raise a sev 3 to ensure our handler is driven*
          *************************************************
               MOVE 3 TO SEV.
               MOVE 1 TO MSGNO.
               MOVE 1 TO CASE.
               MOVE 3 TO SEV2.
               MOVE 1 TO CNTRL.
               MOVE "CEE" TO FACID.
               MOVE 0 TO ISINFO.
    
               CALL "CEENCOD" USING SEV, MSGNO, CASE,
                   SEV2, CNTRL, FACID, ISINFO, CONDTOK, FC.
               IF NOT CEE000 of FC  THEN
                   DISPLAY "CEENCOD failed with msg "
                       Msg-No of FC UPON CONSOLE
                   STOP RUN
               END-IF.
    
          *************************************************
          ** Call CEESGL to signal the condition with    **
          **     the condition token and qdata described **
          **     in CONDTOK and QDATA                    **
          *************************************************
               MOVE 0 TO QDATA.
               CALL "CEESGL" USING CONDTOK, QDATA, FC.
               IF NOT CEE000 of FC  THEN
                   DISPLAY "CEESGL  failed with msg "
                       Msg-No of FC UPON CONSOLE
                   STOP RUN
               END-IF.
    
               GOBACK.
  3. Following is an example of a COBOL user-written condition handler that is registered by CBLHDLR and unregistered by CBLHDLU.
    CBL LIB,QUOTE,NOOPT,NODYNAM
          *Module/File Name: IGZTHAND
          *************************************************
          **                                             **
          ** DRVHAND - Drive sample program for COBOL    **
          **           user-written condition handler.   **
          **                                             **
          *************************************************
           IDENTIFICATION DIVISION.
           PROGRAM-ID. DRVHAND.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01  ROUTINE             PROCEDURE-POINTER.
           01  DENOMINATOR         PIC S9(9) BINARY.
           01  NUMERATOR           PIC S9(9) BINARY.
           01  RATIO               PIC S9(9) BINARY.
           01  TOKEN               PIC S9(9) BINARY VALUE 0.
           01  FC.
               02  Condition-Token-Value.
               COPY  CEEIGZCT.
                   03  Case-1-Condition-ID.
                       04  Severity    PIC S9(4) BINARY.
                       04  Msg-No      PIC S9(4) BINARY.
                   03  Case-2-Condition-ID
                             REDEFINES Case-1-Condition-ID.
                       04  Class-Code  PIC S9(4) BINARY.
                       04  Cause-Code  PIC S9(4) BINARY.
                   03  Case-Sev-Ctl    PIC X.
                   03  Facility-ID     PIC XXX.
               02  I-S-Info            PIC S9(9) BINARY.
    
           PROCEDURE DIVISION.
    
           REGISTER-HANDLER.
          ************************************************
          ** Register handler                           **
          ************************************************
               SET ROUTINE TO ENTRY "HANDLER".
               CALL "CEEHDLR" USING ROUTINE , TOKEN , FC.
               IF  NOT CEE000 of FC  THEN
                   DISPLAY "CEEHDLR failed with msg "
                       Msg-No of FC UPON CONSOLE
                   STOP RUN
               END-IF.
    
           RAISE-CONDITION.
          ************************************************
          ** Cause a zero-divide condition.             **
          ************************************************
               MOVE 0 TO DENOMINATOR.
               MOVE 1 TO NUMERATOR.
               DIVIDE NUMERATOR BY DENOMINATOR
                      GIVING RATIO.
               DISPLAY "Execution continues following "
                   "divide-by-zero exception".
           UNREGISTER-HANDLER.
          ************************************************
          ** UNregister handler                         **
          ************************************************
               CALL "CEEHDLU" USING ROUTINE, TOKEN, FC.
               IF NOT CEE000 of FC  THEN
                   DISPLAY "CEEHDLU failed with msg "
                       Msg-No of FC UPON CONSOLE
               END-IF.
               STOP RUN.
           END PROGRAM DRVHAND.
    
           IDENTIFICATION DIVISION.
           PROGRAM-ID. HANDLER.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
    
           LINKAGE SECTION.
           01  TOKEN                   PIC S9(9) BINARY.
           01  RESULT                  PIC S9(9) BINARY.
               88 RESUME                   VALUE 10.
           01  CURCOND.
               02  Condition-Token-Value.
               COPY  CEEIGZCT.
                   03  Case-1-Condition-ID.
                       04  Severity    PIC S9(4) BINARY.
                       04  Msg-No      PIC S9(4) BINARY.
                   03  Case-2-Condition-ID
                             REDEFINES Case-1-Condition-ID.
                       04  Class-Code  PIC S9(4) BINARY.
                       04  Cause-Code  PIC S9(4) BINARY.
                   03  Case-Sev-Ctl    PIC X.
                   03  Facility-ID     PIC XXX.
               02  I-S-Info            PIC S9(9) BINARY.
           01  NEWCOND.
               02  Condition-Token-Value.
               COPY  CEEIGZCT.
                   03  Case-1-Condition-ID.
                       04  Severity    PIC S9(4) BINARY.
                       04  Msg-No      PIC S9(4) BINARY.
                   03  Case-2-Condition-ID
                             REDEFINES Case-1-Condition-ID.
                       04  Class-Code  PIC S9(4) BINARY.
                       04  Cause-Code  PIC S9(4) BINARY.
                   03  Case-Sev-Ctl    PIC X.
                   03  Facility-ID     PIC XXX.
               02  I-S-Info            PIC S9(9) BINARY.
           PROCEDURE DIVISION USING CURCOND, TOKEN,
                                    RESULT, NEWCOND.
    
           PARA-HANDLER.
               DISPLAY "Entered user handler for condition"
                  " with message number " Msg-No Of CURCOND
                  " -- will resume execution".
               SET RESUME TO TRUE.
    
               GOBACK.
           END PROGRAM HANDLER.
  4. Following is an example of a PL/I program to handle divide-by-zero condition.
    *Process macro;
     /* Module/File Name: IBMHDLR                        */
     /****************************************************/
     /*                                                  */
     /*  EXCOND               .-> DIVZERO                */
     /*  - register handler   |   - force a divide-by-0  */
     /*  - call DIVZERO     --'                          */
     /*  ==> "resume point"                              */
     /*  - unregister handler                            */
     /*                         USRHDLR:                 */
     /*                         - if divide-by-zero then */
     /*                           - move resume cursor   */
     /*                           - resume at "resume"   */
     /*                                          point   */
     /*                                                  */
     /****************************************************/
     Excond :Proc Options(Main);
    
       /**************************************************/
       /* Important elements are found in these includes */
       /* - feedback declaration                         */
       /* - fbcheck macro call                           */
       /* - condition tokens such as CEE000              */
       /* - entry declarations such as ceehdlr           */
       /**************************************************/
    
       %include ceeibmct;
       %include ceeibmaw;
    
       dcl Usrhdlr external entry;
    
       dcl 1 fback feedback;
       dcl divisor fixed bin(31);
       dcl token   fixed bin(31);
    
       /*********************************************/
       /* Register a user-written condition handler */
       /*********************************************/
       token = 97;
       Call ceehdlr(Usrhdlr, token, fback);
       If fbcheck (fback, cee000) then
         display ('MAIN: registered USRHDLR');
       else
         do;
           display ('CEEHDLR failed with message number ' ||
                     fback.MsgNo);
           stop;
         end;
    
       /*********************************************/
       /* Call DIVZERO to divide by zero            */
       /*  and drive USRHDLR                        */
       /*********************************************/
       divisor = 0;
       call divzero (divisor);
       display ('MAIN: resumption after DIVZERO');
     /*********************************************/
       /* Unregister the user condition handler     */
       /*********************************************/
    
       Call ceehdlu (Usrhdlr, fback);
       If fbcheck (fback, cee000) then
         display ('MAIN: unregistered USRHDLR');
       else
         do;
           display ('CEEHDLU failed with message number ' ||
                     fback.MsgNo);
           stop;
         end;
    
         /*********************************************/
         /* Subroutine that simply raises ZERODIVIDE  */
         /*********************************************/
         divzero: proc (arg);
           dcl arg fixed bin(31);
    
           display('  DIVZERO: starting.');
           arg = 1 / arg;
           display('  DIVZERO: Returning to its caller');
    
         end divzero;
    
     end Excond;
  5. Following is an example of CEEHDLR called by PL/I.
    AHDL     TITLE 'Main program that registers a handler'
    *
    *        Symbolic Register Definitions and Usage
    *
    R0       EQU   0             Parm list addr (CMS only)
    R1       EQU   1             Parm list addr, 0=no parms
    R10      EQU   10            Base reg for executable code
    R12      EQU   12            Language Environment Common Anchor Area addr
    R13      EQU   13            Dynamic Storage Area addr
    R14      EQU   14            Return point addr
    R15      EQU   15            Entry point address
    *
    *        Prologue
    *
    CEEHDLRA CEEENTRY AUTO=DSASIZ,    Main memory to obtain   *
                   MAIN=YES,     This program is a MAIN prog  *
                   PPA=PPA1,     Our Program Prolog Area      *
                   BASE=R10      Base reg for executable code
             USING CEECAA,R12    Addressing for LE/370 CAA
             USING CEEDSA,R13    Addressing for dynamic data
    *
    *        Announce ourselves
    *
             WTO   'CEEHDLRA Says "HELLO"',ROUTCDE=11
    *
    *        Register User Handler
    *
             LA    R1,USRHDLPP   Get addr of proc-ptr to Hdlr
             ST    R1,PARM1      Make it 1st parameter
             LA    R1,TOKEN      Get addr of 32-bit token
             ST    R1,PARM2      Make it 2nd parameter
             LA    R1,FEEDBACK   Get addr of feedback code
             ST    R1,PARM3      Make it 3rd parameter
             LA    R1,HDLRPLST   Point to CEEHDLR's parm list
             CALL  CEEHDLR       Invoke CEEHDLR service
             CLC   FEEDBACK,=XL12'00' Check for success..
             BE    HDLRGOOD      Skip diagnostics if success
    *                            Failure.. issue diagnostics
             WTO   '**** Call to CEEHDLR failed ****',        *
                    ROUTCDE=11
             ABEND 1,DUMP        Terminate program with Dump
    HDLRGOOD EQU   *             Handler registered OK
    *  ... code covered by User-Written Handler goes here...
    *        Un-Register User Handler
    *
             LA    R1,USRHDLPP   Get addr of proc-ptr to Hdlr
             ST    R1,HDLUPRM1   Make it 1st parameter
             LA    R1,HDLUFBC    Address for feedback code
             ST    R1,HDLUPRM2   Make it 2nd parameter
             LA    R1,HDLUPLST   Point to CEEHDLU parm list
             CALL  CEEHDLU       Invoke CEEHDLU service
    *        Bid a fond farewell
             WTO   'CEEHDLRA Says "GOOD-BYE"',ROUTCDE=11
    *
    *        Epilogue
    *
             CEETERM RC=4,MODIFIER=1  Terminate program
    *
    *        Program Constants and Local Static Variables
    *
    USRHDLPP DC    V(USRHDLR),A(0)    Procedure-ptr to Handlr
    *
             LTORG ,                  Place Literal Pool here
             EJECT
    PPA1     CEEPPA ,            Our Program Prolog Area
             EJECT
             CEEDSA ,            Map CEE Dynamic Save Area
    *
    *        Local Automatic (Dynamic) Storage.
    *
    HDLRPLST DS    0F
    PARM1    DS    A             Addr of User-written Handler
    PARM2    DS    A             Addr of 32-bit Token
    PARM3    DS    A             Addr of feedback code
    *
    HDLUPLST DS    0F
    HDLUPRM1 DS    A             Addr of User-written Handler
    HDLUPRM2 DS    A             Addr of feedback code
    *
    TOKEN    DS    F             32-bit Token: fullword whose
    *                                 *value* will be passed
    *                                 to the user handler
    *                                 each time it is called.
    FEEDBACK DS    CL12          CEEHDLR Feedback code
    *
    HDLUFBC  DS    CL12          CEEHDLU Feedback code
    *
    DSASIZ   EQU   *-CEEDSA      Length of DSA
             EJECT
             CEECAA ,            Map LE370 Common Anchor Area
             END   CEEHDLRA