CEEHDLR—Register user-written condition handler
- 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.
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
- For more information about the CEEHDLU callable service, see CEEHDLU—Unregister user-written condition handler.
Examples
- 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) { /* ⋮ */ }
- 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.
- 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.
- 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;
- 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