A new version of Kernel was added to project The Inbox:
http://source.squeak.org/inbox/Kernel-jar.1410.mcz==================== Summary ====================
Name: Kernel-jar.1410
Author: jar
Time: 21 May 2021, 3:55:35.689716 pm
UUID: 8f28f106-e393-2a4f-beb1-c6e955c155fe
Ancestors: Kernel-nice.1402
Prevent VM crashes due to returning from #cannotReturn. The fix introduces a isRecursive variable to BlockCannotReturn to recognize an infinite loop.
#cannotReturn: loops to itself and notifies the user an infinite loop is starting. Returning from #cannotReturn: is no longer possible so that the user cannot crash the VM by accidentally pressing Proceed, by stepping over etc. #terminate can take advantage of this improved behavior.
This is a more sophisticated alternative to Kernel-jar.1404 for a discussion.
Examples like:
[^2] fork
or
[[self error] ensure: [^2]] fork
or even
a := [true ifTrue: [^ 1] yourself]
"and then do-it separately (c) Christoph:"
[a value] on: BlockCannotReturn do: [:ex | ex resume]
can no longer crash the image :)
=============== Diff against Kernel-nice.1402 ===============
Item was changed:
Error subclass: #BlockCannotReturn
+ instanceVariableNames: 'result deadHome isRecursive'
- instanceVariableNames: 'result deadHome'
classVariableNames: ''
poolDictionaries: ''
category: 'Kernel-Exceptions'!
!BlockCannotReturn commentStamp: '<historical>' prior: 0!
This class is private to the EHS implementation. Its use allows for ensured execution to survive code such as:
[self doThis.
^nil]
ensure: [self doThat]
Signaling or handling this exception is not recommended.!
Item was added:
+ ----- Method: BlockCannotReturn>>isRecursive (in category 'accessing') -----
+ isRecursive
+
+ ^isRecursive ifNil: [false]!
Item was added:
+ ----- Method: BlockCannotReturn>>isRecursive: (in category 'accessing') -----
+ isRecursive: aBoolean
+
+ ^isRecursive := aBoolean!
Item was changed:
----- Method: Context>>cannotReturn: (in category 'private-exceptions') -----
cannotReturn: result
+ closureOrNil ifNotNil: [self cannotReturn: result to: self home sender.
+ [self cannotReturnRecursive: result to: self home sender.
+ self notify: '#cannotReturn: Invoking an infinite loop'.
+ true] whileTrue].
- closureOrNil ifNotNil: [^ self cannotReturn: result to: self home sender].
Processor debugWithTitle: 'Computation has been terminated!!' translated full: false.!
Item was added:
+ ----- Method: Context>>cannotReturnRecursive:to: (in category 'private-exceptions') -----
+ cannotReturnRecursive: result to: homeContext
+ "The receiver tried to return result to homeContext that no longer exists.
+ This is a repeated invocation of the BlockCannotReturn error."
+
+ ^BlockCannotReturn new
+ result: result;
+ deadHome: homeContext;
+ isRecursive: true;
+ signal!