[squeak-dev] The Trunk: Kernel-jar.1478.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jun 9 08:16:02 UTC 2022

Marcel Taeumel uploaded a new version of Kernel to project The Trunk:

==================== Summary ====================

Name: Kernel-jar.1478
Author: jar
Time: 8 June 2022, 11:16:07.949882 pm
UUID: f5720d99-9ce2-374c-adb0-811c23b2cfe5
Ancestors: Kernel-jar.1477

Fix a bug in #runUntilReturnFrom:: while searching for a context that cannot return (to avoid the VM crash) I forgot to limit the search to the relevant part of the stack only (i.e. search only *between* the contexts to be executed). As a result the following example currently fails to unwind:

p := [[[^2] on: BlockCannotReturn do: [Semaphore new wait]] ensure: [Transcript show: 'been here ']] fork.
Processor yield.
[p terminate] fork

Plus a minor change to allow unwinding even in this case:

p := [[] ensure: [[[^2] on: BlockCannotReturn do: [Semaphore new wait]] ensure: [Transcript show: 'been here ']]] fork.
Processor yield.
[p terminate] fork

A test will follow later.

=============== Diff against Kernel-jar.1477 ===============

Item was changed:
  ----- Method: Context>>runUntilReturnFrom: (in category 'private-exceptions') -----
  runUntilReturnFrom: aContext
  	"Run the receiver (which must be its stack top context) until aContext returns. Avoid a context that cannot return.
  	 Note: to avoid infinite recursion of MNU error inside unwind blocks, implement e.g. a wrapper around the message
  	 sentTo: receiver in #doesNotUnderstand:. Note: This method is a trivialized version of #runUntilErrorOrReturnFrom:
  	 and was intended to be used by #unwindTo as a helper method to unwind non-local returns inside unwind blocks."
  	| here unwindBottom newTop |
  	here := thisContext.
+ 	"Avoid a context that cannot return between self and aContext (see Note 1 below)."
+ 	unwindBottom := self findContextSuchThat: [:ctx | ctx == aContext or: [ctx selector = #cannotReturn:]].
+ 	newTop := unwindBottom sender.
- 	"Avoid a context that cannot return (see Note 1 below)"
- 	unwindBottom := (self findContextSuchThat: [:ctx | ctx selector = #cannotReturn:]) ifNil: [aContext].
- 	newTop := aContext sender.
  	"Insert ensure context under unwindBottom in self's stack (see Note 2 below)"
  	unwindBottom insertSender: (Context contextEnsure: [here jump]).
  	self jump.  "Control jumps to the receiver's stack (see Note 2 below)"
  	"Control resumes here once the above inserted ensure block is executed (see #jump comments)"
  	^newTop  "Return the new top context (see Note 3 below)"
  	"Note 1: returning from #cannotReturn's sender would crash the VM so we install a guard ensure context right
  	 above it; after returning here the unwind will continue safely. Try running and debugging this example
  	 (avoid Proceeding the BCR error though; it may indeed crash the image):
  	 [[[] ensure: [^2]] ensure: [^42]] fork"
  	"Note 2: the receiver (self) is run by jumping directly to it (the active process abandons thisContext and executes
  	 self on its own stack; self must be its top context). However, before jumping to self we insert an ensure block under
  	 unwindBottom context that will execute a jump back to thisContext when evaluated. The inserted guard ensure
  	 context is removed once control jumps back to thisContext."
  	"Note 3: it doesn't matter newTop is not a proper stack top context because #unwindTo will only use it as a starting
  	 point in the search for the next unwind context and the computation will never return here. We could make newTop
  	 a proper top context by pushing nil to its stack (^newTop push: nil) if need be (see #jump comments).
  	 Cf. the pattern in #runUntilErrorOrReturnFrom:: removing the inserted ensure context by stepping until popped
  	 when executing non-local returns wouldn't work here and would fail tests testTerminateInNestedEnsureWithReturn1
  	 through 4."!

More information about the Squeak-dev mailing list