Bug #10624
DO WHILE that contains a FINALLY block can be executed too many times
100%
Related issues
History
#1 Updated by Paul Bodale 10 months ago
- Status changed from New to WIP
During the testing of a customer application I found that the following testcase is the subject of a problem in FWD:
DEFINE VARIABLE i AS INTEGER NO-UNDO INITIAL 0.
DO WHILE NOT (i = 1) ON ERROR UNDO, THROW:
MESSAGE i.
FINALLY:
i = i + 1.
END FINALLY.
END.
This prints 0 and 1 in FWD and only 0 in Progress.
The problem is that if the condition of a DO WHILE block is dependent on the execution of a FINALLY block then the block of the DO WHILE will be executed 1 more time than it should.
#3 Updated by Paul Bodale 10 months ago
- % Done changed from 0 to 50
- Status changed from WIP to Review
- reviewer Alexandru Lungu, Constantin Asofiei added
Created task branch 10624a and committed rev. 16186 which fixes the problem encountered in the customer's app.
I only fixed the behavior for the specific testcase above. The same procedure can be applied to the other loop blocks that can also have FINALLY block. But before then, I'll put this in review so that if anybody else thinks of a better solution we can discuss it here.
#4 Updated by Alexandru Lungu 9 months ago
I am OK with the approach in 10624a, but I would also like a second opinion from Constantin.
My concern is mostly on:- As you mention, other looping blocks (e.g. REPEAT)
- How database statements interact with the finally (e.g.
FOR EACH tt WHILE NOT (i = 1)) - How is error handled (ON ERROR UNDO, THROW shall call finally afterwards, right?)
- Please also check if CATCH blocks have the same behavior (if exceptions are caught for each iteration, or only once).
#5 Updated by Eduard Soltan 6 months ago
- Related to Bug #4602: fixes for OO 4GL and structured error handling added
#6 Updated by Eduard Soltan 6 months ago
Alexandru Lungu wrote:
- How is error handled (ON ERROR UNDO, THROW shall call finally afterwards, right?)
I have some pending changes that does just that, error handling and control-of-flow statements (LEAVE, NEXT, or RETRY, etc) raised inside the CATCH or FINALLY blocks. We worked together with Paul on integrating 10624a changes into 4602a.
- Please also check if CATCH blocks have the same behavior (if exceptions are caught for each iteration, or only once).
CATCH block do have the same behaviour, and the exception is caught on each iteration.
#7 Updated by Eduard Soltan 6 months ago
Committed on 4602a, integration of the changes from 10624a.
#8 Updated by Paul Bodale 6 months ago
- % Done changed from 50 to 100
The tests I wrote touch on all points provided by Alex here. I will commit them on the testcases project under the tests/base_language/blocks/finally folder folder.
Alexandru Lungu wrote:
My concern is mostly on:
- As you mention, other looping blocks (e.g. REPEAT)
Tested DO index = start TO finish, DO WHILE condition, REPEAT and also FOR EACH statements.
- How database statements interact with the finally (e.g.
FOR EACH tt WHILE NOT (i = 1))
I've found that while this is possible, it is never recommended as it is very easy to screw up by unintentionally starting new transactions, masking original errors, and also the case when program is exiting due to a STOP or QUIT condition.
These come as a consequence to the fact that "The transaction of the associated block is either complete (success) or undone (failure) when FINALLY executes." The transaction of the associated block has already ended by the time the FINALLY block starts.
- How is error handled (ON ERROR UNDO, THROW shall call finally afterwards, right?)
As far as I've tested, the behavior is the same as a normal block. ON ERROR UNDO, THROW is default for the FINALLY block.
- Please also check if CATCH blocks have the same behavior (if exceptions are caught for each iteration, or only once).
Eduard tested this and yes, they have the same behavior.