Handling errors in CL Programs

465 pts.
Tags:
CL Program
Control Language Programming
ILE Program
iSeries
I've been searching all over the internet (and this site) looking for a good way to generically handle errors within a CL program.  Everything's seems very vauge to me. What I'm looking to do is something like this:
CHGSPLFA   FILE(&SPOOLFILE) SAVE(*NO)  
MONMSG     MSGID(CPF0000)  EXEC('SEND EMAIL WITH ERROR MESSAGE DETAILS TO A USER AND EXIT PROGRAM')        
I'd like to know the line it failed at, and all of the message details in the email.  I know you can do EXEC(GOTO CMDLBL(ERROR)) and use SNDDST to send the email.  I'm not really sure how to pull the information our of the exception thrown. I'm so used to taking care of business with try{} catch(e){} in other languages that I never really learned about proper error handling in CL. Thanks in advance for the help! Dave

Software/Hardware used:
CL, ILE, iSeries, V5R4
ASKED: February 22, 2011  9:10 PM
UPDATED: February 23, 2011  4:54 PM

Answer Wiki

Thanks. We'll let you know when a new response is added.

Then MONMSG command can be very useful.It is usually used to catch & FIX errors on the fly. For every command there are specific messages you can monitor for. If a member is not found in a file, you can monitor for that and add the member and keep on going.When using MONMSG, you need to determine what errors are HARD STOPS and what ones can you ignore, make adjustments if necessary and continue processing. You can also have them setup so they will send a message and halt the process until a response is revceived.
From your requirements stated above, you may just want to do DSPJOBLOG OUTPUT(*PRINT) . That would give you the information on where it failed,
*
So what I am trying to say here, is first determine the types of errors you want to check for and the types of responces you want to have. Then you can update your CL programs to hanbdle the specific issues.
Remember the EXEC portion of the MONMSG can be DO, and you can issue multiple commands and/or call a variety of programs.
*
How this helped some.

Discuss This Question: 3  Replies

 
There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when members answer or reply to this question.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
  • TomLiotta
    The handling of errors in CL (or any compiled language under the OS/400 scheme) essentially requires a basic understanding of how messages are handled. Exceptions are generally signaled through the sending of messages. If you receive those messages, you can extract almost anything you'd ever need to know. As an introduction, here is a trivial CL program that causes an error and then receives the two relevant messages:
    pgm
    
       dcl   &KeyVar      *char    4
       dcl   &MsgTxt      *char  132
       dcl   &MsgLen      *dec (   5 0 )
       dcl   &MsgDta      *char  512
       dcl   &MsgDtaLen   *dec (   5 0 )
       dcl   &MsgId       *char    7
       dcl   &Sender      *char  720
    
       call     ABCDXYZMN
       monmsg ( cpf0000 )  exec( callsubr HandleErr )
    
       return
    
       subr     HandleErr
    
       rcvmsg      msgtype( *LAST ) rmv( *NO ) +
                     keyvar( &KeyVar ) +
                     msg( &MsgTxt ) msglen( &MsgLen ) +
                     msgdta( &MsgDta ) msgdtalen( &MsgDtaLen ) +
                     msgid( &MsgId ) +
                     sender( &Sender ) +
                     senderfmt( *LONG )
    
       dmpclpgm
    
       rcvmsg      msgtype( *PRV ) msgkey( &KEYVAR ) rmv( *NO ) +
                     keyvar( &KeyVar ) +
                     msg( &MsgTxt ) msglen( &MsgLen ) +
                     msgdta( &MsgDta ) msgdtalen( &MsgDtaLen ) +
                     msgid( &MsgId ) +
                     sender( &Sender ) +
                     senderfmt( *LONG )
    
       dmpclpgm
    
       endsubr
    
    endpgm
    The program simply calls another program named "ABCDXYZMN". Assuming that no such program exists in the library list, that will cause an error. The general error will be CPF0001, "Error found on CALL command." That's an error relating to almost any kind of command on the system, and it indicates that the command simply can't complete as compiled. There's nothing wrong with the syntax; it just won't work. The CPF0001 is sent as a fairly non-specific *ESCAPE message. The *ESCAPE message is the signaling of failure. But before that message was sent, another one was sent -- CPD0170, "Program ABCDXYZMN in library *LIBL not found." That was sent as a *DIAG (Diagnostic) message. Diagnostic messages carry some details about exactly what went wrong. There might be multiple *DIAG messages accompanying an *ESCAPE message. In this case there is only one. In practice, you might have the second RCVMSG in a loop for the Diagnostics in order to receive all of them. Now, the example doesn't actually do anything except retrieve message attributes in some variables and then run dumps. Without knowing what you'll do, there's no way to really code any actions. But you can compile and run the program, and then compare the dumped variables against the help text of the RCVMSG parms. Also, compare the values against message details that you might see in the joblog. You should be able to recognize stuff. For example, if you look at positions 645-648 of the &Sender variable in the dump, you should see that it matches the "To statement" statement number in the message details for the message in the joblog. There is too much information about sending and receiving messages. A truly "generic" handling of them could probably be done, but specific handling usually works out better. Try running the above program. Review the info that gets captured. Compare it against the RCVMSG help text for the parms that I used (and note that others are available). See what comes to mind. Then ask followup questions for any details that aren't clear. Keep in mind that *ESCAPE messages signal failure of something. I've had circumstances where "failures" mean that attempts to run any additional processing simply cause additional errors. 'Generic' handling of errors just might not work in a failure scenario. Tom
    125,585 pointsBadges:
    report
  • Dcantwell
    OK. Thanks for the info Tom and Charlie. I've come up with some code based on your posted code Tom:
                 PGM
    
                 DCL        VAR(&KEYVAR) TYPE(*CHAR) LEN(4)
                 DCL        VAR(&MSGTXT) TYPE(*CHAR) LEN(132)
                 DCL        VAR(&MSGLEN) TYPE(*DEC) LEN(5 0)
                 DCL        VAR(&MSGDTA) TYPE(*CHAR) LEN(512)
                 DCL        VAR(&MSGDTALEN) TYPE(*DEC) LEN(5 0)
                 DCL        VAR(&MSGID) TYPE(*CHAR) LEN(7)
                 DCL        VAR(&SENDER) TYPE(*CHAR) LEN(720)
                 DCL        VAR(&EMAIL) TYPE(*CHAR) LEN(60) +
                              VALUE(email@email.COM)
                 DCL        VAR(&N) TYPE(*CHAR) LEN(3) VALUE(':/N')
                 DCL        VAR(&P) TYPE(*CHAR) LEN(3) VALUE(':/P')
    
                 /*Let's call this a hard error. We want to leave the program*/
                 CALL       PGM(ABCDXYZMN)
                 MONMSG     MSGID(CPF0000) EXEC(CALLSUBR HANDLEERR)
    
                 RETURN
                 SUBR       SUBR(HANDLEERR)
    
                    RCVMSG     MSGTYPE(*LAST) RMV(*NO) KEYVAR(&KEYVAR) +
                                 MSG(&MSGTXT) MSGLEN(&MSGLEN) MSGDTA(&MSGDTA) +
                                 MSGDTALEN(&MSGDTALEN) MSGID(&MSGID) +
                                 SENDER(&SENDER) SENDERFMT(*LONG)
    
                    SNDDST     TYPE(*LMSG) TOINTNET((&EMAIL) (*NONE *CC)) +
                                 DSTD('FINANCIAL SERVICES IMAGING ERROR') +
                                 LONGMSG('MSGID:' |> &MSGID |> &P || 'Message +
                                 Text:' |> &MSGTXT |> &P || 'Message Data:' |> +
                                 &MSGDTA |> &P || 'END ERROR') AUTHOR(DAVEC) +
                                 DISCLOSE(*YES) ALWX400CNV(*NO)
    
                    RCVMSG     MSGTYPE(*PRV) MSGKEY(&KEYVAR) RMV(*NO) +
                                 KEYVAR(&KEYVAR) MSG(&MSGTXT) MSGLEN(&MSGLEN) +
                                 MSGDTA(&MSGDTA) MSGDTALEN(&MSGDTALEN) +
                                 MSGID(&MSGID) SENDER(&SENDER) SENDERFMT(*LONG)
    
                    SNDDST     TYPE(*LMSG) TOINTNET((&EMAIL) (*NONE *CC)) +
                                 DSTD('FINANCIAL SERVICES IMAGING ERROR') +
                                 LONGMSG('MSGID:' |> &MSGID |> &P || 'Message +
                                 Text:' |> &MSGTXT |> &P || 'Message Data:' |> +
                                 &MSGDTA |> &P || 'END ERROR') AUTHOR(DAVEC) +
                                 DISCLOSE(*YES) ALWX400CNV(*NO)
                 ENDSUBR
    
                 ENDPGM     
    
    Here's my new questions:
    1. Will there always be two messages? If not, will I have to monitor another message ID to make sure I don't retrieve a non-existent message?
    2. I've identified I'd like to do a hard stop as you mentioned Charlie. How Do I make sure the program stops? With the subroutine as it is, I can't use "GOTO" with a command label because it causes a compile error. Can I simply use a "RETURN" statement in the subroutine? ENDPGM?
    3. Looking a the &Sender value I noticed the error was coming at '000F', which would be 16 and corresponds to the 16th line of my code which is the program call. Am I reading this correctly Tom?
    465 pointsBadges:
    report
  • Dcantwell
    [...] CharlieBrowne and TomLiotta are thorough and helpful in this inquiry about handling errors in CL programs. 6. The whole gang’s here! Mrdenny, Ingram87, IceCubbe, Rechil, Sixball, Redtyke, and [...]
    0 pointsBadges:
    report

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

To follow this tag...

There was an error processing your information. Please try again later.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy

Thanks! We'll email you when relevant content is added and updated.

Following