Hello,
On 10/6/2010 7:17 PM, Alan Campin wrote:
I indicated in one of my previous posts how to reproduce the issue. If you
are in the same program and issue the error there it is not a problem.
For anyone who wants to see what Alan is describing, try the following
*SRVPGM. It runs in the TRYAG2 activation group, and deliberately
crashes (by sending an *ESCAPE message) -- as Alan describes, this will
end the TRYAG2 activation group:
*> CRTRPGMOD TRYAG2 SRCFILE(QRPGLESRC) DBGVIEW(*LIST)
*> CRTSRVPGM TRYAG2 EXPORT(*ALL) ACTGRP(TRYAG2)
H NOMAIN
D TRYAG2 pr
P TRYAG2 b export
D QMHSNDPM PR ExtPgm('QMHSNDPM')
D MessageID 7A Const
D QualMsgF 20A Const
D MsgData 32767A Const options(*varsize)
D MsgDtaLen 10I 0 Const
D MsgType 10A Const
D CallStkEnt 10A Const
D CallStkCnt 10I 0 Const
D MessageKey 4A
D ErrorCode 8192A options(*varsize)
d MsgKey s 4a
d ErrorCode ds
d x 10i 0 inz(0)
d y 10i 0 inz(0)
/free
QMHSNDPM( 'CPF9897'
: 'QCPFMSG *LIBL'
: 'Test'
: 4
: '*ESCAPE'
: '*'
: 0
: MsgKey
: ErrorCode );
/end-free
P e
To see the problem this causes, call it from the following progam...
this program runs in a different activation group (TRYAG1.) It calls
the preceding service program, and catches the error when it crashes.
It then tries to call it again, but this will fail with "Attempt made to
reference to an object that no longer exists".
The reason it does this: When RPG called tryag2() the first time, the
*SRVPGM was loaded, and a procedure pointer was found that points to the
tryag2() procedure. When tryag2() crashed, however, the TRYAG2
activation group ended. When it tries to call it again, it's still
trying to use the same pointer (which is no longer valid). What it
_should_ do (IMHO) is reactivate the *SRVPGM, and use a new pointer...
but it makes no attempt to do that, it just tries to call the old
pointer, and fails:
*> CRTRPGMOD TRYAG1 SRCFILE(QRPGLESRC) DBGVIEW(*LIST)
*> CRTPGM TRYAG1 BNDSRVPGM(TRYAG2) ACTGRP(TRYAG1)
D tryag2 pr
/free
monitor;
tryag2();
on-error;
endmon;
tryag2();
*inlr = *on;
/end-free
You could solve the problem by reclaiming the TRYAG1 activation group
(this'll cause the pointer to be reset), or by handling the procedure
pointer logic manually in your program.
Or (and IMHO this is what Alan _should_ do) code TRYAG2 to catch all
errors so that it never crashes.
Note that this error is a bit contrived... normally, you'd code a
*SRVPGM with ACTGRP(*CALLER), and in that case, this would never happen.
As an Amazon Associate we earn from qualifying purchases.