*INLR, Return combined

21 Views


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 with RETURN (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.


 

Post Comments