On 02-Sep-2015 15:11 -0600, Monnier, Gary wrote:
On 02-Sep-2015 14:16 -0600, James Rich wrote:
On Wed, 2 Sep 2015, Buck Calabro wrote:
On 9/2/2015 3:36 PM, Charles Wilt wrote:
On 02-Sep-2015 13:31 -0600, James Rich wrote:
We want to send an email if our nightly closing/backup stops
on any kind of error. I thought about monitoring for CPF0000
but I think that will prevent the job from stopping with a
MSGW. I still want the job to stop with MSGW on the line
where the error occurred, I just need some facility to notice
that a MSGW condition exists and send an email. Any
suggestions?

Can't be done.

Either the job stops, or the job doesn't stop (and sends an
email).

You'd need an external process that monitors for the MSGW and
sends an email.

A possible alternative is to MONMSG (ie trap the error), in the
DO() send the email and then re-throw the exception.

I thought about this but couldn't come up with a satisfactory way
to do it. Many programs are called during the execution of the
daily close and I'd want execution to stop at the original point of
execution of the error.

<<SNIP>>
If you are wanting to monitor application program errors why not
have the programmers incorporate error handling into their programs?

So true, a proactive approach is good. But...

Allowing the default handler for the language to process the unmonitored error conditions is what allows for "the job to stop with MSGW on the line where the error occurred," That quote would seem to imply that the OP wants the code to remain dependent upon the language's default handler for unmonitored conditions, and to act reactively.?

Coding to override the default handler with generic or specific monitors and handlers is often quite appropriate [e.g. in CL by trapping errors with Monitor Message (MONMSG)], but using those prevents enabling the R=Retry for the failing statement, as provided with the language-specific default-handler. For example, if there is an unexpected authority error for which the ability might exist to Grant authority as corrective, while the job waits, that ability can be *much nicer* than the application having thrown an error about bad_thing within a DOWHILE (*NOT &SUCCESS) loop, or worse throwing the error about bad_thing but then just exiting the program such that the entire CL\process must be restarted.

Anyhow, FWiW, some comments about the code snippets continued inline:


For CL do something like this...

At top of program put in this line to handle errors globally.

MonMsg MsgID(CPF0000 MCH0000) Exec(Goto HandleErr)


To get nearer to the failing statement, the global handler should just set on an error indicator [or set of a success indicator], and each phase of the program should be coded to loop until OK to move to the next phase; inquiring when not OK, to allow the review of the


/* your program does stuff here */

Presumably the HandleErr should be reached only per the GOTO in the global monitor [and possibly more specific monitors]; i.e. probably missing here is:

GOTO PgmEnd


HandleErr:

/*---------------------------------------*/
/* Receive and resend Diagnostic message */
/*---------------------------------------*/

RcvMsg MsgType(*DIAG) MsgDta(&msgData) MsgDtaLen(&msgDtaLen) +
MsgID(&msgID) MsgF(&msgFile) msgFLib(&msgLib)

That is a FIFO operation, and the result may not be what is desired; typically the final diagnostic is more pertinent, and generally is received as *PRV to the key for the Exception message.


MonMsg MsgID(CPF0000 MCH0000) exec(GoTo PgmEnd)

Monitoring for MCH0000 is poor form; mostly, if ever a request fails with a MCHxxxx [the out-dated MCH3601 for unspecified Return Values is one exception to that rule], the exception condition should *not* be monitored, and the unmonitored condition processing and the language-specific default handler should run. The MCH0000 is implicitly monitored by the inclusion of CPF0000 because that includes CPF9999, but only after the unmonitored condition is dealt with.


If (&msgID *NE ' ') Then(Do)

DMPCLPGM
DSPJOBLOG JOB(*) OUTPUT(*PRINT)

The above two CL command\statements /need/ to have MONMSG to prevent a loop; no different than the next statement. Merely the likelihood that they will never fail with one of the generically globally monitored messages is probably not a justifiable rationale, considering the consequences for what could be a relatively /tight/ exception loop.


SndPgmMsg MsgID(&msgId) MsgF(&msgLib/&msgFile) +
MsgDta(&msgData) ToPgmQ(*PRV) MsgType(*DIAG)
MonMsg MsgID(CPF0000 MCH0000) /* you don't want to loop */

The better option is to Move the diagnostic [and other; e.g. informational] messages; there may be several rather than just one message, depending on what failed, and no messing with message data.

/* Or call a program that sends an email and also sends an inquiry message to QSYSOPR */
/* call YourPgmName PARM(&rtncode &sndmsg &sndmsgfile &sndmsglib &sndmsgdta) */
/* MonMsg MsgID(CPF0000 MCH0000) Exec(Do) */
/* do what you will */
/* enddo */
GoTo PgmEnd

With the above GOTO, the processing of the Exception message would be skipped; seems unintended.


EndDo

/*-----------------------------------*/
/* Receive and resend Escape message */
/*-----------------------------------*/

RcvMsg MsgType(*EXCP) MsgDta(&msgData) MsgDtaLen(&msgDtaLen) +
MsgID(&msgID) MsgF(&msgFile) msgFLib(&msgLib)
MonMsg MsgID(CPF0000 MCH0000) exec(GoTo PgmEnd)

Similar to aforementioned moving of messages, there is a Resignal message capability for the Exception message; again, no mucking about with message data [that could have been declared too small and thus resulting in loss of details in the resent copy].


If (&msgID *NE ' ') Then(Do)

If only an Exception-type of message could have gotten here, then if that COND() is not true, then the OS has a serious problem.

SndPgmMsg MsgID(&msgId) MsgF(&msgLib/&msgFile) +
MsgDta(&msgData) ToPgmQ(*PRV) MsgType(*ESCAPE)
MonMsg MsgID(CPF0000 MCH0000)
/* Or call a program that sends an email and also sends an inquiry message to QSYSOPR */
/* call YourPgm PARM(&rtncode &sndmsg &sndmsgfile &sndmsglib &sndmsgdta) */
/* MonMsg MsgID(CPF0000 MCH0000) Exec(Do) */
/* do what you will */
/* enddo */
GoTo PgmEnd

EndDo

GoTo PgmEnd

You can use whatever you currently use to send the email.

<<SNIP>>



This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].