[squeak-dev] Solving multiple termination bugs - summary & proposal

Jaromir Matas m at jaromir.net
Wed May 19 17:38:52 UTC 2021

Hi Christoph, hi all,

I've updated my #terminate fix to a "final" version Kernel-jar.1409 in the

I'm still 100% convinced completing unwind block halfway-through their
execution is a good idea; and it's not my idea ;) 

If a process gets interrupted or is suspended in the middle of unwinding, it
should be allowed to finish all unwind blocks - both halfway-through and
not-yet-started. It's not necessarily a case of a raised error or abandoning
the debugger - it's a general termination procedure. If we say Abandoning a
debugger equals terminating the debugged process then we should terminate it
including all unwinds. If we don't want to equate Abandon to general
termination that doesn't mean we have to change the termination logic - we
should rather change the Abandoning logic in such case :) 

I think ProcessTest >> #testNestedUnwind illustrates the idea clearly:

x1 := x2 := x3 := nil.
			[ ] ensure: [ "halfway through completion when suspended"
				[ ] ensure: [ "halfway through completion when suspended"
					Processor activeProcess suspend. "here the process gets terminated"
					x1 := true]. 
				x2 := true]
		] ensure: [ "not started yet when suspended"
			x3 := true]
] fork.
Processor yield.
p terminate
self assert: x1 & x2 & x3.

There was nothing wrong with the process p when it got terminated in the
first place and thus there's no reason to prevent it from finishing all its
unwind blocks.

> [...] the fact that an error has been signaled means that the
> signalerContext is "infected" so under no circumstances, abandoning the
> process should resume the execution of this infected context!

You cannot know whether an error will be raised during termination - so you
should not be changing the general termination logic but rather adjusting
the "debugger abandon/termination" logic; currently the consensus is:
debugger Abandon equals process termination but that's not necessarily so... 

> Instead of reinventing the unwinding wheel in Process, I reused the
> existing logic from Context which
> is important deduplication. 

Well, actually I didn't reinvent the unwind pattern but intentionally reused
it with as few changes as possible - I think it improves readability because
people easily recognize this pattern from #resume:, #resume:through:,
#unwindTo and even the previous #terminate used the exact same pattern for
an active process termination. Besides, using the same pattern for achieving
a similar goal feels "safer" to me.

> Instead of modifying #runUntilErrorOrReturnFrom:, I have moved the logic
> to re-signal the UnhandledError into Process >> #complete:ifError:. [...]
> The #resumeUnchecked: part could
> actually be relevant if there occurs a second UnhandledError while jumping
> out of reorf.

Yes indeed, I made a silly assumption but reverted the change back already
in Kernel-jar.1408. I use its modified replica instead.

> I think that the fact that you needed to skip certain exceptions manually
> was a giant suboptimal hack. :-)

Yes, it was a sort of my to-do list ;) I've sorted out the
MessageNotUnderstood but BlockCannotReturn is still a hot topic :)

> I always recommend using as many block-local temps as possible, this makes
> it easier to understand their
> scope. In case you haven't heard it before, you might also want to google
> Guard Clause. :-) 

Again, I wanted to make as few changes as possible; but agreed absolutely :)

Thanks again very much for your comments.
best regards,

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

More information about the Squeak-dev mailing list