Version: trunk [r13331] (Linux x86_64); also [r13297], so not a regression. Component: interpreter (RexxActivation).
An internal routine shares its caller's condition traps and ADDRESS WITH configuration until it changes them; then it gets copies of its own. Through INTERPRET, the change goes into the caller's tables instead:
call on halt name gotIt -- the caller has a trap table
call off halt
say "1." sig()
x = .T~new~r -- an untrapped NOTREADY in the caller
say "2. goes on, x=" || x
exit 0
gotIt: return
sig: procedure
interpret "signal on notready name trapped"
x = .T~new~r
return "not trapped"
trapped:
return "trapped" condition("C")
::class T
::method r
raise notready return 8
Expected: 1. trapped NOTREADY, then 2. goes on, x=8. Actual: after 1., the caller's untrapped NOTREADY jumps to trapped: in the main program, and its RETURN ends the program silently (exit 0). The same happens with an INTERPRETed CALL ON (the caller's untrapped condition runs the routine's handler) and with ADDRESS WITH: interpret "address command with output stem d." in an internal routine sends the caller's later command output to d.. Written out, without INTERPRET, SIGNAL ON and ADDRESS WITH are right, and a caller with no trap table yet is not affected.
There is a second hole for ADDRESS WITH, without INTERPRET: a routine A that has set its own configuration calls a routine B that sets another one; back in A, the output goes to B's stem.
Cause (RexxActivation.cpp): checkTrapTable() and checkIOConfigTable() copy the shared table only when isInternalCall(). An INTERPRET activation takes the settings of the code that runs it and gives them back when it ends, so it writes into the table that the routine still shares with its caller. And the constructor resets trapsCopied for an internal call, but not ioConfigCopied, so B inherits A's "already copied" flag and writes into A's table.
Fix (3 lines): copy also when isInterpret() (the copy goes back to the routine with its settings, as if the routine had made the change itself), and reset ioConfigCopied for an internal call, as trapsCopied is.
Tests: 4 in ooRexx/base/keyword/INTERPRET.testGroup (INTERPRETed SIGNAL ON, CALL ON, nested INTERPRET, and a caller with SIGNAL ON instead of CALL ON; the programs run as routines made with .Routine~new, so that the group's ::OPTIONS ALL SYNTAX does not apply, with a NOTREADY from CHARIN of a file that does not exist), and 4 in ooRexx/base/keyword/ADDRESS.testGroup (the two holes above, INTERPRET in a routine whose caller has a configuration, and a check that what INTERPRET sets is still the routine's).
Results on [r13331], Linux, Release: INTERPRET.testGroup 15/15 and ADDRESS.testGroup 84/84 with the fix (without it, the 4 new INTERPRET tests and 3 of the 4 new ADDRESS tests fail); full test suite with no differences except the 8 new tests. Patches attached (main, test).
Commit: [r13297]
Commit: [r13331]
Anonymous