Hi Christoph,
Christoph Thiede wrote
[ [ [ ] ensure: [ [] ensure: [ ^Transcript show: 'x1']. Transcript show: 'x2'] ] ensure: [ Transcript show: 'x3']. Transcript show: 'x4' ] fork
In this case the expected outcome is ---> x1 x3. Neither x2 nor x4
should be printed (x2 is intentionally skipped by the non-local return and x4 is outside the ensure blocks). With the fix you propose the outcome is either ---> x1 x2 x3 if pressed Abandon or ---> x1 x2 x3 x4 if pressed Proceed - this would be equivalent to no non-local return at all :)
Wait, wait, wait. This smells to me. :-) #cannotReturn: should not be *resumed* after the error was abandoned. Otherwise, something is wrong with the termination logic. Process >> #terminate *must not* resume in this place. Terminating means only executing all uncompleted unwind contexts. I just reverted to the version ct 1/17/2021 18:35 of Process >> #terminate and with regard to your example, both implementations of #cannotReturn: behave the save (---> x1 x3) as expected. Hm, I'm sorry, but Process >> #terminate is not yet done correctly IMHO.
What happened: in your changeset you made #cannotReturn: return to its sender after choosing Proceed, i.e. the execution continued into the preceding #ensure context. This, I feel, introduces an incorrect semantics here: the real sender of the #cannotReturn: was the VM that tried to execute a non-local return and failed. For lack of other options (I guess) the VM set the #ensure: context as a sender of #cannotReturn: - my guess the main purpose of this link is to keep the stack chain available for unwind - but not for resuming the execution - so this is my objection.
Proceeding after BlockCannotReturn actually means: Proceed as if no non-local return was ever there. This doesn't seem right to me but maybe there could be good a reason to do this in debugging, I don't know.
The crucial point here is #terminate now attempts to complete the outer-most unfinished unwind block instead of the inner-most only (i.e. the deepest unfinished unwind block as opposed to the most shallow one). In this particular example current #terminate correctly leaves the unfinished unwind block after abandoning BlockCannotReturn (skipping 'x2') and finds another unwind block with 'x3'. But if you apply your #cannotReturn patch and press Proceed then #cannotReturn: returns and current #terminate simply continues the unwind within the current unwind block and finds 'x2'.
To avoid any confusion: by no means #terminate resumes after BlockCannotReturn - absolutely not, #terminate just continues unwinding remaining unwind blocks only; that's different.
With your example, you won't be able to escape from the situation without pressing Abandon.
Well, yes, that was the point: I can't imagine a reasonable next step from a non-local return with no home context to return to... That's why I looped #cannotReturn: to itself with the only way out via Abandon, i.e. terminating :)
I'm sending an alternative proposal to solve the infinite recursion of BlockCannotReturn:
``` cannotReturn: result
closureOrNil ifNotNil: [self cannotReturn: result to: self home sender. [self cannotReturnRecursive: result to: self home sender. self notify: 'Invoking an infinite loop'. true] whileTrue]. Processor debugWithTitle: 'Computation has been terminated!' translated full: false. ```
where #cannotReturnRecursive:to: sets a Boolean variable for the user to be able to deal with the recursion. Resuming BCR or not should no longer be an issue...
I know you're questioning whether Abandoning the debugger should be equivalent to terminating; or more precisely you're suggesting termination logic should be reduced to follow a normal return or exception return logic, i.e. skipping the unwind blocks currently under evaluation as discussed in [1]. As you know I disagree here and maintain the general termination logic should be as broad as possible but I see your point in reducing the termination logic in case of abandoning a debugger in case the debugged process is broken.
Thanks and best regards!
[1] http://forum.world.st/The-semantics-of-halfway-executed-unwind-contexts-duri...
----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html