ILE RPG Exception Handling
Exceptions: If a
program doesn’t behave in its normal way and discontinues or gets interrupted
further processing, then it is called exception.
There are 2
classes of exceptions that we may face:
1.
File exception
e.g. Undefined record type or a device error, Record
lock, Update operation attempted without a prior read
2.
Program exception
e.g. Divide by zero, array index out-of-bound,
Invalid Date, Time or Timestamp value.
We can see all the program/file related system messages
using the command below:
DSPMSGD RANGE(*FIRST *LAST) MSGF(QRNXMSG) DETAIL(*BASIC)
The below table lists some of the commonly used
Status Codes.
MSG ID MESSAGE DETAIL
00100 Value out of range for string operation
00102 Divide by zero
00112 Invalid Date, Time or Timestamp value.
00121 Array index not valid
00122 OCCUR outside of range
00202 Called program or procedure failed
00211 Error calling program or procedure
00222 Pointer or parameter error
00401 Data area specified on IN/OUT not found
00413 Error on IN/OUT operation
00414 User not authorized to use data area
00415 User not authorized to change data area
00907 Decimal data error (digit or sign not valid)
01021 Tried to write a record that already exists (file being used has unique keys
and key is duplicate, or attempted to write duplicate relative record number to
a subfile).
01211 File not open.
01218 Record already locked.
01221 Update operation attempted without a prior read.
Status codes
%STATUS provides a five-digit status code that identifies the
error. Program status codes are in the range 00100 to 00999 and File status
codes are in the range 01000 to 01999. Status codes in the range 00000 to 00050
are considered to be normal (i.e., they are not set by an exception/error condition).
ILE RPG provides
four methods of handling RPG exceptions with the exception handling priority
decreasing from 1st to 4th:
- Specify an error indicator in positions 73 - 74 of the calculation specifications of the appropriate
operation code.
Or,
Specify the operation code extender 'E' for the appropriate operation code.
Either of these two can be used at a time but not both.
- Include the code that produces the exception within a MONITOR group.
- Code a file error
subroutine, which is defined by the INFSR keyword on a file description specification, for file
exceptions. The file error subroutine can only be coded in the main source
section. You cannot code an INFSR for a file that is used in a subprocedure.
Or,
Code a program error subroutine, which is named *PSSR, for program exceptions. Note
that a *PSSR is local to the procedure in which it is coded. This means that a
*PSSR in a main procedure will handle only those program errors associated with
the main procedure. Similarly, a *PSSR in a subprocedure will only handle the
errors in that subprocedure.
4.
Default
exception handler
Priority of Exception handling
If any exception occurs then as per the highest
priority the error indicator or ‘E’ operator extender will be checked if it no
found then the unhandled exception( as it was not handled by this 1st
method) will look for MONITOR block. If MONITOR block is also not present then
it will look for File exception/error subroutine(INFSR) or program
exception/error subroutine (*PSSR). If after this also the exception remains
unhandled then it will go for default handler.
Examples:
All above 4 methods with examples are
given below:
1. (a) Using Error indicator
If an error
indicator is present on the calculation specification and the exception is one
that is expected for that operation:
- The indicator is set on
- The exception is handled
- Control resumes with the next
ILE RPG operation.
Columns . . . : 6 80 Browse AMITCC/QRPGLESRC
SEU==> E_OP_EXTN2
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data ****************************************************
0001.00 HOPTION(*SRCSTMT) 130122
0002.00 FCUST UF A E DISK USROPN 130122
0003.00 130121
0004.00 C 1 SETLL CUSTR 66 130122
0005.00 C EXSR @ERROR 130122
0006.00 C EVAL CSNAME='AMI' 130122
0007.00 C UPDATE CUSTR 66 130122
0008.00 C EXSR @ERROR 130122
0009.00 C SETON LR 130122
0010.00 * 130122
0011.00 C @ERROR BEGSR 130122
0012.00 C IF *IN66=*ON 130122
0013.00 C IF %STATUS(CUST)=1211 130122
0014.00 C OPEN CUST 130122
0015.00 C ELSEIF %STATUS(CUST)=1221 130122
0016.00 C READ(E) CUST 130122
0017.00 C EVAL CSNAME='AMI' 130122
0018.00 C UPDATE(E) CUSTR 130122
0019.00 C ENDIF 130122
0020.00 C ENDIF 130122
0021.00 C ENDSR 130122
****************** End of data ******************************************************
OUTPUT
File CUST will
be updated successfully.
1. (b) Using Operator Extender (E)
If an 'E'
operation code extender is present on the calculation specification and error
indicator is not present then the error occurred will be handled by this
operator extender.
But this
operator extender’s use is limited only to the op-codes listed below:
ACQ CLOSE OCCUR REL
TEST
ADDDUR COMMIT OPEN RESET
UNLOCK
ALLOC DEALLOC NEXT ROLBK
UPDATE
CALL DELETE OUT REALLOC
WRITE
CALLB DSPLY POST SCAN
XLATE
CALLP EXFMT READ SETGT
XML-INTO
CHAIN EXTRCT RAEDE SETLL
XML-SAX
CHECK FEOD READP SUBDUR
CHECKR IN READPE SUBST
The error will
be handled using the built-in functions %STATUS and %ERROR.
Control
resumes with the next ILE RPG operation.
·
ERROR HANDLING USING
E-OPERATOR EXTENDER BUT NOT HANDLING ERROR WITH %ERROR
Columns . . . : 6 80 AMITCC/QRPGLESRC
SEU==> E_OP_EXTN3
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data *************************************************
0001.00 HOPTION(*SRCSTMT) 130122
0002.00 FCUST UF A E DISK USROPN 130122
0003.00 130121
0006.00 C 1 SETLL(E) CUSTR 130123
0008.00 C EVAL CSNAME='AMI' 130123
0009.00 C UPDATE(E) CUSTR 130122
0011.00 C SETON LR 130122
****************** End of data ******************************************************
OUTPUT
Here
you won't get any error but there will be logical error i.e. file CUST will not
get updated.
·
ERROR HANDLING USING
E-OPERATOR EXTENDER AND %ERROR BUILT-IN FUNCTION
Columns . . . : 6 80 AMITCC/QRPGLESRC
SEU==> E_OP_EXTND
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data ************************************************
0001.00 HOPTION(*SRCSTMT) 130122
0002.00 FCUST UF A E DISK USROPN 130122
0003.00 130121
0004.00 C 1 SETLL(E) CUSTR 130123
0005.00 C EXSR @ERROR 130123
0006.00 C EVAL CSNAME='CCC' 130123
0007.00 C UPDATE(E) CUSTR 130122
0008.00 C EXSR @ERROR 130123
0009.00 C SETON LR 130122
0010.00 * 130122
0011.00 C @ERROR BEGSR 130122
0012.00 C IF %ERROR() 130122
0013.00 C IF %STATUS(CUST)=1211 130122
0014.00 C OPEN CUST 130122
0015.00 C ELSEIF %STATUS(CUST)=1221 130122
0016.00 C READ(E) CUST 130122
0017.00 C EVAL CSNAME='CCC' 130123
0018.00 C UPDATE(E) CUSTR 130122
0019.00 C ENDIF 130122
0020.00 C ENDIF 130122
0021.00 C ENDSR 130122
****************** End of data ****************************************************
OUTPUT
File CUST will be updated successfully.
2. Using Monitor Block
§ If no error indicator or 'E' extender is present
and the code that generates the exception is in the MONITOR block of a MONITOR
group, control will pass to the on-error section of the MONITOR group.
§ V5R1 saw the introduction of a MONITOR group: it
allows you to monitor a number of statements for potential errors, as opposed
to checking them one at a time.
§ The code for which you want to trap exception
errors is placed in a MONITOR group. If an exception/error is issued for any of
the operations (between the MONITOR and the first ON-ERROR operation), control
passes to the first ON-ERROR statement.
§ After the MONITOR statement, control passes to
the next statement.
§ If all the statements in the MONITOR block are
processed without errors, control passes to the statement following the ENDMON
statement.
§ The monitor group can be specified anywhere in
calculations. It can be nested within IF, DO, SELECT, or other monitor groups.
The IF, DO, and SELECT groups can be nested within monitor groups.
§ If a monitor group is nested within another
monitor group, the innermost group is considered first when an error occurs. If
that monitor group does not handle the error condition, the next group is
considered.
§ Monitor block structure:
Monitor;
// Code to monitor
On-Error statuscode1 : statuscode2 :statuscode3;
// Handle Error related to statuscode1 or statuscode2 or statuscode3
On-Error *FILE;
// Handles all file-error status codes, from 01000 to 09999
On-Error *PROGRAM;
// Handles all program-error status codes, from 00100 to 00999
On-Error *ALL;
// Handles both program-error and file-error codes, from 00100 to 09999. This is the
default.
EndMon;
Example
Columns . . . : 6 80 Browse AMITCC/QRPGLESRC
SEU==> MONITORPG2
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data *******************************************************
0001.00 HOPTION(*SRCSTMT)
0002.00 FCUST UF A E DISK USROPN
0003.00
0004.00 *_________________________________________________________
0005.00 *
0006.00 C MONITOR
0007.00 *_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
0008.00 *
0009.00 C MONITOR
0010.00 C 1 SETLL CUSTR
0011.00 C ON-ERROR 1211 >>>>>>> If the error is ‘file CUST not OPEN’, then
0012.00 C OPEN CUST open the file CUST
0013.00 C ENDMON
0014.00 *_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
0015.00 *
0016.00 C MONITOR
0017.00 C EVAL CSNAME='OOO'
0018.00 C UPDATE CUSTR
0019.00 C ON-ERROR 1215 >>> If the error is ‘Update without prior INPUT/READ
0020.00 C READ(E) CUST operation’, then READ the file.
0021.00 C EVAL CSNAME='OOO'
0022.00 C UPDATE(E) CUSTR
0023.00 C ENDMON
0024.00 *_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
0025.00 *
0026.00 C ON-ERROR *FILE
0027.00 C DUMP(A) >>> If the error is ‘any unhandled file error’ then
0028.00 C ON-ERROR take the DUMP’.
0029.00 C DUMP(A)
0030.00 C ENDMON
0031.00 *_________________________________________________________
0032.00 *
0033.00 C SETON LR
0034.00 *
0035.00 *
****************** End of data ***********************************************************
3. Using *PSSR for program exception & INFSR for
file exception
If No error indicator or 'E' extender is
present, No active MONITOR group
could handle the exception, then the exception handling will be done by:
- *PSSR error subroutine
for program exception/errors.
Or,
- INFSR error subroutine for
the file and the exception is an I/O exception,
The control will resume
at the first statement of the error subroutine.
¤ 2 Ways to handle file
error/exceptions:
a.
INFSR (File
Error subroutine name)
First we can mention INFSR
(INFSR1) keyword where INFSR1 is the user defined file error subroutine.
b.
INFSR
(*PSSR)
Second way is to use *PSSR
program error subroutine to handle the file errors. Specifying
INFSR (*PSSR)
means that you want the
"standard" *PSSR subroutine to handle the file exceptions also along
with
program exceptions.
a.
INFSR (File
Error subroutine name)
Example:
Columns . . . : 6 80 Browse AMITCC/QRPGLESRC
SEU==> PSSR_PGM2
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data *****************************************************
0001.00 HOPTION(*SRCSTMT) 130122
0002.00 FCUST UF A E DISK USROPN INFSR(INFSR1) 130122
0003.00 F INFDS(INFDS1) 130122
0004.00 DINFDS1 DS 130122
0005.00 DFILE_STATUS *STATUS 130122
0006.00 * 130122
0007.00 C N441 SETLL CUSTR 130124
0008.00 C EVAL CSNAME='LLL' 130122
0009.00 C UPDATE CUSTR 130122
0010.00 C SETON LR 130122
0011.00 * 130122
0012.00 C INFSR1 BEGSR 130122
0013.00 C IF FILE_STATUS=1211 130122
0014.00 C OPEN CUST 130122
0015.00 C MOVE '*GETIN' Returncd 6 130124
0016.00 C ELSEIF FILE_STATUS=1221 130123
0017.00 C READ(E) CUST 130122
0018.00 C EVAL CSNAME='LLL' 130122
0019.00 C SETON 44 130124
0020.00 C MOVE '*GETIN' Returncd 130124
0021.00 C ELSE 130123
0022.00 C MOVE '*CANCL' Returncd 130124
0023.00 C ENDIF 130122
0024.00 C ENDSR Returncd 130124
****************** End of data *********************************************************
*** The INFSR
keyword cannot be specified if the keyword NOMAIN is specified on the control
specification or if the file is to be accessed by a subprocedure or in other
words we can't use a file in a subprocedure if the INFSR keyword is coded for
the file.
INFSR (*PSSR)
This is the 2nd way to handle file
exception/erros.
When we don't use INFSR(*PSSR) then
*PSSR subroutine only handles program errors, not the file errors. But when we
mention INFSR(*PSSR), then the exception is handled for file error by *PSSR.
Columns . . . : 6 80 Browse AMITCC/QRPGLESRC
SEU==> PSSR_PGM4
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data ***************************************************
0001.00 HOPTION(*SRCSTMT) 130122
0002.00 FCUST UF A E DISK USROPN INFSR(*PSSR) 130131
0003.00 F INFDS(INFDS1) 130122
0004.00 DINFDS1 DS 130122
0005.00 DFILE_STATUS *STATUS 130122
0006.00 * 130122
0007.00 C N441 SETLL CUSTR 130124
0008.00 C EVAL CSNAME='MMM' 130131
0009.00 C UPDATE CUSTR 130122
0010.00 C SETON LR 130122
0011.00 * 130122
0012.00 C *PSSR BEGSR 130131
0013.00 C IF FILE_STATUS=1211 130122
0014.00 C OPEN CUST 130122
0015.00 C MOVE '*GETIN' Returncd 6 130124
0016.00 C ELSEIF FILE_STATUS=1221 130123
0017.00 C READ(E) CUST 130122
0018.00 C EVAL CSNAME='MMM' 130131
0019.00 C SETON 44 130124
0020.00 C MOVE '*GETIN' Returncd 130124
0021.00 C ELSE 130123
0022.00 C MOVE '*CANCL' Returncd 130124
0023.00 C ENDIF 130122
0024.00 C ENDSR Returncd 130124
****************** End of data *******************************************************
The problem with PSSR concept is its
poor handling of nested errors. If an error occurs inside of a PSSR, it will
invoke the PSSR again, recursively. So unless you have a bunch of code in place
to detect the nested failure, your program will go into a hard loop.
Hence, by using INFSR (*PSSR), we can make
a single *PSSR subroutine that will handle both file exceptions and program
exceptions exception.
Example: Single *PSSR handling both file
and program exceptions.
Columns . . . : 6 80 Browse AMITCC/QRPGLESRC
SEU==> PSSR_PGM5
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data ****************************************************
0001.00 HOPTION(*SRCSTMT) 130122
0002.00 FCUST UF A E DISK USROPN INFSR(*PSSR) 130131
0003.00 F INFDS(INFDS1) 130122
0004.00 DINFDS1 DS 130122
0005.00 DFILE_STATUS *STATUS 130122
0006.00 * 130122
0007.00 DMYPSDS SDS 130131
0008.00 DPROC_NAME *PROC 130131
0009.00 * Procedure name 130131
0010.00 DPGM_STATUS *STATUS 130131
0011.00 * Status code 130131
0012.00 D LINE_NUM 21 28 130131
0013.00 * Source statement line no. 130131
0014.00 * 130131
0015.00 130131
0016.00 DA S 2 0 INZ(*ZEROS) 130131
0017.00 DB S 2 0 INZ(10) 130131
0018.00 DC S 2 0 INZ(*ZEROS) 130131
0019.00 D@ERR S 50 INZ(*BLANKS) 130131
0020.00 * 130131
0021.00 C B DIV A C 667788 130131
0022.00 C TAG1 TAG 130131
0023.00 C 'C=Infinite' DSPLY 130131
0024.00 130131
0025.00 C TAG2 TAG 130131
0026.00 C N441 SETLL CUSTR 130124
0027.00 C EVAL CSNAME='MMM' 130131
0028.00 C TAG3 TAG 130131
0029.00 C UPDATE CUSTR 130122
0030.00 C SETON LR 130122
0031.00 * 130122
0032.00 C *PSSR BEGSR 130131
0033.00 C IF FILE_STATUS=01211 130131
0034.00 C OPEN CUST 130122
0035.00 C GOTO TAG2 130131
0036.00 C ELSEIF FILE_STATUS=01221 130131
0037.00 C READ(E) CUST 130122
0038.00 C EVAL CSNAME='MMM' 130131
0039.00 C SETON 44 130124
0040.00 C GOTO TAG3 130131
0041.00 C ELSEIF FILE_STATUS=00000 AND PGM_STATUS=00000 130131
0042.00 C LEAVESR 130131
0043.00 C ELSEIF FILE_STATUS=00000 AND PGM_STATUS<>00000 130131
0044.00 C*------------------Do nothing 130131
0045.00 C ELSE 130131
0046.00 C 'FILE ERR' DSPLY 130131
0047.00 C MOVE '*CANCL' Returncd 6 130131
0048.00 C ENDIF 130122
0049.00 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 130131
0050.00 C IF PGM_STATUS=00102 130131
0051.00 C EVAL @ERR='Error at line no.'+ 130131
0052.00 C LINE_NUM + ' with status code '+ 130131
0053.00 c %CHAR(PGM_STATUS) 130131
0054.00 C @ERR DSPLY 130131
0055.00 C RESET PGM_STATUS 130131
0056.00 C GOTO TAG1 130131
0057.00 C ELSEIF PGM_STATUS=00000 130131
0058.00 C LEAVESR 130131
0059.00 C ELSE 130131
0060.00 C 'PGM ERR' DSPLY 130131
0061.00 C MOVE '*CANCL' Retur 6 130131
0062.00 C ENDIF 130131
0063.00 C RESET PGM_STATUS 130131
0064.00 C ENDSR Returncd 130124
0065.00 130131
****************** End of data *******************************************************
Output
DSPLY Error at line no.00002100 with status code 102
DSPLY C=Infinite
4. Default exception handler
If no error indicator, 'E' extender, or error
subroutine is coded and no active MONITOR group could handle the exception,
then the RPG default error handler is invoked.
a. If the exception is not a function
check, then the exception will be percolated.
b. If the exception is a function check, then an
inquiry message will be displayed. If the 'G' or 'R' option is chosen, the
function check will be handled and control will resume at the appropriate point
(*GETIN for 'G' or the same calculation specification that received the
exception for 'R') in the procedure. Otherwise, the function check will be
percolated and the procedure will be abnormally terminated.
Example
In the snapshot below we get closed
file error and the message is sent
to the External message queue with an inquiry message that is because the
default exception handler comes into play the role of exception handling.
Display Program Messages
Job 915341/IROBO/QPADEV0007 started on 01/23/13 at 01:21:10 in subsystem QINT
I/O operation was applied to closed file CUST (C G D F).
Type reply, press Enter.
Reply . . ._______________________________________________________________
____________________________________________________________________________
F3=Exit F12=Cancel
Press F1 on the message to see the details:
Additional Message Information
Message ID . . . . . . : RNQ1211 Severity . . . . . . . : 99
Message type . . . . . : Inquiry
Date sent . . . . . . : 01/23/13 Time sent . . . . . . : 01:23:24
Message . . . . : I/O operation was applied to closed file CUST (C G D F).
Cause . . . . . : RPG procedure E_OP_EXTND in program AMITCC/E_OP_EXTND at
statement 000600 attempted operation SETLL on file CUST while the file was
closed.
Recovery . . . : Contact the person responsible for program maintenance to
determine the cause of the problem.
Possible choices for replying to message . . . . . . . . . . . . . . . :
D -- Obtain RPG formatted dump.
S -- Obtain system dump.
G -- Continue processing at *GETIN.
C -- Cancel.
F -- Obtain full formatted dump.
Bottom
Press Enter to continue.
F3=Exit F6=Print F9=Display message details
F10=Display messages in job log F12=Cancel F21=Select assistance level
Differences between
OPM and ILE RPG Exception Handling
The main difference between the handling of OPM and ILE RPG
exception handling is Percolation.
¤ Percolation
In an OPM environment, a program that is well down the call
stack receives an exception/error. If the program does not have any exception/error
handling, the RPG default handler will issue a function check message.
In an ILE environment, a subprocedure or a program that is
well down the call stack receives an exception/error. If the subprocedure or
program does not have any exception/error handling specified, the message is
sent back up the call stack to the calling procedure. If the calling procedure
does not have any exception/error handling defined, the message is again sent
back up the call stack to the calling procedure and so on until the AG control
boundary is reached.
For example, consider the following example:
- PGM A
calls PGM B, which in turn calls PGM C.
- PGM B has
an error indicator coded for the call.
- PGM C has
no error indicator or *PSSR error subroutine coded.
- PGM C gets
an exception.
In OPM, an inquiry message would be issued for PGM C. In
ILE, the exception is percolated to PGM B, since it is unhandled by PGM C. The
error indicator in PGM B is turned on allowing PGM B to handle the error, and
in the process PGM C ends abnormally. There is no inquiry message.
If PGM C has
a *PSSR error subroutine coded, then in both OPM and ILE, the exception is
handled by PGM C and the error subroutine is run.
Example
Columns . . . : 6 80 Edit AMITCC/QRPGLESRC
SEU==> E_OP_EXTN4
FMT H HKeywords++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*************** Beginning of data ****************************************************
0001.00 HDftActGrp(*No) ActGrp('TEST1') 130124
0002.00 DCALL1 PR 130124
0003.00 * 130124
0004.00 DMYPSDS SDS 130124
0005.00 DPROC_NAME *PROC 130124
0006.00 * Procedure name 130124
0007.00 DPGM_STATUS *STATUS 130124
0008.00 * Status code 130124
0009.00 D LINE_NUM 21 28 130124
0010.00 * Source statement line no. 130124
0011.00 * 130124
0012.00 D@ERR S 50 INZ(*BLANKS) 130124
0013.00 130121
0014.00 C N44 CALLP CALL1 130124
0015.00 C SETON LR 130122
0016.00 * 130122
0017.00 C *PSSR BEGSR 130124
0018.00 C IF PGM_STATUS=00202 130124
0019.00 C EVAL @ERR='Error at line no.'+ 130124
0020.00 C LINE_NUM + ' with status code '+ 130124
0021.00 C %CHAR(PGM_STATUS) 130124
0022.00 C @ERR DSPLY 130124
0023.00 C MOVE '*GETIN' Returncd 6 130124
0024.00 C ELSE 130124
0025.00 C 'FATAL ERR' DSPLY 130124
0026.00 C MOVE '*CANCL' Returncd 130124
0027.00 C ENDIF 130124
0028.00 C SETON 44 130124
0029.00 C ENDSR Returncd 130124
0030.00 130124
0031.00 * 130124
0032.00 PCALL1 B 130124
0033.00 Da s 1 0 inz(*zeros) 130124
0034.00 Db s 2 0 inz(10) 130124
0035.00 Dc s 1 0 inz(*zeros) 130124
0036.00 C EVAL c=b/a 130124
0037.00 PCALL1 E 130124
0038.00 * 130124
****************** End of data *******************************************************
Output
DSPLY Error at
line no.00000014 with status code 202
The above output had become possible
because of percolation only.4
Exception Handling
within Subprocedures
Exception handling within a subprocedure differs from a
main procedure in the following ways:
- Because
you cannot code an INFSR subroutine, you should handle file errors using
error indicators, the 'E' operation code extender, or a MONITOR group.
- There is
no default handler; in other words, users will never see an inquiry
message.
Exception handling within a subprocedure differs
from a main procedure primarily because there is no RPG cycle code generated
for subprocedures. As a result there is no default exception handler for
subprocedures and so situations where the default handler would be called for a
main procedure correspond to abnormal end of the subprocedure. This means that:
- Factor 2
of an ENDSR operation for a *PSSR subroutine within a subprocedure must be
blank i.e. we cannot use *GETIN,
*CANCL or *DETC for factor 2 as it is used in a
case we are dealing with default exception handler.
- If there
is no *PSSR and a function check occurs, the procedure is removed from the
call stack and the exception is percolated to the caller.
- Since an
inquiry message is never issued for an error in a subprocedure, you do not
have access to the 'Retry' function available for some I/O errors. If you
expect record-lock errors in a subprocedure, you should code an error
indicator or an 'E' extender and check if the status is related to a
record being locked.
·
A *PSSR is local to the procedure in which it is coded; therefore,
to have a common error routine, you can code a procedure to handle the error
and call the procedure from each local *PSSR.