Let's break down the difference between *INLR = *ON
alone vs. *INLR = *ON
followed by RETURN
in an RPGLE (ILE RPG) program — and why the combination is essential in most cases.
โ
1. *INLR = *ON
Alone
*inlr = *on;
// no RETURN
๐ What happens:
-
*INLR = *ON
sets the Last Record flag, telling IBM i:-
"This program is done"
-
"You can release files, memory, ODPs"
-
-
However, it does NOT end the program!
-
The program keeps running unless it naturally reaches the end or hits a
RETURN
.
๐งจ Risk:
If you forget to follow it with RETURN
, the program might:
-
Fall through other logic unintentionally
-
Continue executing code you didn't intend to run
โ
2. *INLR = *ON
+ RETURN
*inlr = *on;
return;
๐ What happens:
-
Tells the system:
-
โ "Clean up everything" (
*INLR
) -
โ "Exit the program now" (
RETURN
)
-
-
This is the standard and safe way to properly end a program.
โ Why They Are Different
Scenario | Behavior |
---|---|
*INLR only |
Flags for cleanup, but doesn't exit the program |
*INLR + RETURN |
Flags cleanup and exits — standard ILE RPG exit method |
RETURN only (no *INLR ) |
Exits the program, but files, ODPs, and memory remain open |
๐งช Real-World Example
Let’s say your program has logic like this:
if condition = 'X';
*inlr = *on;
endif;
// Unexpected code below
doSomething();
If the condition is true, *INLR = *ON
is set — but since there's no RETURN
, the program continues and runs doSomething()
— possibly causing bugs.
โ Best Practice: Always Combine
*inlr = *on;
return;
This ensures:
-
Files are closed
-
Static storage is released
-
Program ends cleanly
-
Prevents residual memory, file locks, ODP issues
Here’s a code example that clearly shows how using *INLR = *ON
without RETURN
can lead to unintended code execution — which can cause bugs, double-processing, or unexpected results in your RPGLE program.
๐ฏ Scenario: Program sets *INLR = *ON
, but forgets RETURN
๐งพ Program: INLRBUG
ctl-opt dftactgrp(*no) actgrp(*caller);
dcl-s processFlag char(1) inz('Y');
if processFlag = 'Y';
*inlr = *on; // Program marks itself for cleanup...
dsply 'Marked for cleanup.';
endif;
// Program continues running!
dsply 'Oops! This code still ran.';
๐งช What Happens When You Run It
Output:
Marked for cleanup.
Oops! This code still ran.
โก Even though you told the system "I'm done" (*INLR = *ON
), the program kept running and executed additional logic.
๐ฅ Real-World Consequences
Issue | Impact |
---|---|
File writes/reads still happen | Duplicated or out-of-place data |
External calls re-triggered | APIs or DB logic fires twice |
Logging / cleanup code reruns | Corrupts logs or state tracking |
โ Corrected Version
ctl-opt dftactgrp(*no) actgrp(*caller);
dcl-s processFlag char(1) inz('Y');
if processFlag = 'Y';
*inlr = *on;
dsply 'Marked for cleanup.';
return; // โ
safely exits the program
endif;
// This will NOT run now
dsply 'Oops! This code still ran.';
Output:
Marked for cleanup.
โก Now the program exits cleanly after cleanup — nothing runs unintentionally.
๐ง Key Lesson
*INLR = *ON
is not an exit. It’s a flag for the OS to clean up.
You must follow it withRETURN
(or allow the program to end naturally).
Great — let’s walk through a practical example showing how forgetting to include RETURN
after *INLR = *ON
can lead to duplicate writes to a file — a very common (and dangerous) mistake in batch or transactional programs.
๐ฏ Scenario
You have a program that:
-
Writes a transaction record to a file
-
Calls
*INLR = *ON
(intending to end the program) -
But forgets
RETURN
-
Then accidentally writes the same record again
๐งพ Step 1: Physical File — TXNLOG
A R TXNREC
A TXNID 5A
A ACTION 20A
Insert a few records to test, or keep it empty initially.
๐งพ Step 2: Program — TXNWRITEBUG
ctl-opt dftactgrp(*no) actgrp(*caller);
dcl-f TXNLOG usage(*update: *output);
dcl-s txnID char(5) inz('T001');
dcl-s action char(20) inz('Deposit');
write TXNREC;
dsply 'First write done.';
// Programmer intends to end here:
*inlr = *on;
// โ BUT forgot to return
// Logic accidentally runs again
write TXNREC;
dsply 'Second (unintended) write!';
๐งช What Happens When You Call It
Output:
First write done.
Second (unintended) write!
File contents:
T001 Deposit
T001 Deposit
๐ฅ The same transaction was written twice, even though the programmer clearly meant to end after the first write.
โ Corrected Version
write TXNREC;
dsply 'First write done.';
*inlr = *on;
return; // โ
Exit cleanly โ no second write
Now the output:
First write done.
File contents:
T001 Deposit
โ Only one record written — as expected.
๐ง Summary: When RETURN
Is Missing
Problem | Result |
---|---|
*INLR = *ON alone |
Program keeps running |
File writes after *INLR |
Cause duplicate data or corruption |
External APIs re-invoked | Could double-charge or re-send data |
๐ก Best Practice
Always use
*inlr = *on; return;
at the end of RPGLE programs (not subprocedures) unless you're keeping the program resident on purpose.