[squeak-dev] The Inbox: Kernel-ct.1405.mcz

Jaromir Matas m at jaromir.net
Fri May 21 12:22:46 UTC 2021

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

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

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!


^[^ Jaromir
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

More information about the Squeak-dev mailing list