[squeak-dev] The Inbox: Kernel-jar.1412.mcz

commits at source.squeak.org commits at source.squeak.org
Mon May 24 21:06:47 UTC 2021


A new version of Kernel was added to project The Inbox:
http://source.squeak.org/inbox/Kernel-jar.1412.mcz

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

Name: Kernel-jar.1412
Author: jar
Time: 24 May 2021, 11:06:42.045885 pm
UUID: a5554c88-2df6-dc43-ad89-8b128c719dcd
Ancestors: Kernel-jar.1411

Fix an issue when a process terminating another process is terminated in the middle of the unwind.

As a result the original process won't finish unwinding and will leave either a suspended process or a chain of unfinished contexts behind (to be GC'd).

This is an update of Kernel-jar.1411 (not replacement).

Complemented by a test: KernelTests-jar.406

=============== Diff against Kernel-jar.1411 ===============

Item was changed:
  ----- Method: Process>>terminate (in category 'changing process state') -----
  terminate 
  	"Stop the process that the receiver represents forever.
  	 Unwind to execute pending ensure:/ifCurtailed: blocks before terminating.
  	 If the process is in the middle of a critical: critical section, release it properly."
  
  	| oldList top ctxt outerMost newTop unwindBlock |
  	"If terminating the active process, suspend it first and terminate it as a suspended process."
  	self isActiveProcess ifTrue: [
  		[self terminate] fork.
  		^self suspend].
  
+ 	[] ensure: [
  	"Always suspend the process first so it doesn't accidentally get woken up.
  	N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al
  	then the process is blocked, and if it is nil then the process is already suspended."
  	oldList := self suspend.
  	suspendedContext ifNil: [^self]. "self is already terminated"
  	"Release any method marked with the <criticalSection> pragma.
  	The argument is whether the process is runnable."
  	self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]).
  
  	top := suspendedContext.
  	suspendedContext := nil. "disable this process while running its stack in active process below"
  	"If terminating a process halfways through an unwind, try to complete that unwind block first;
  	if there are multiple such nested unwind blocks, try to complete the outer-most one; nested 
  	unwind blocks will be completed in the process. Halfway-through blocks have already set the 
  	complete variable (tempAt: 2) in their defining #ensure:/#ifCurtailed contexts from nil to true.
  	Note: #findNextUnwindContextUpTo: starts searching from the receiver's sender but the receiver 
  	itself may be an unwind context."
  	ctxt := top.
  	ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil].
  	[ctxt isNil] whileFalse: [
  		(ctxt tempAt:2) ifNotNil: [
  			outerMost := ctxt].
  		ctxt := ctxt findNextUnwindContextUpTo: nil].
  	outerMost ifNotNil: [newTop := self complete: top to: outerMost].
  
  	"By now no halfway-through unwind blocks are on the stack. Create a new top context for each 
  	pending unwind block (tempAt: 1) and execute it on the unwind block's stack. 
  	Note: using #value instead of #complete:to: would lead to incorrect evaluation of non-local returns.
  	Note: newTop sender points to the former outerMost sender, i.e. the next unexplored context."
  	ctxt := newTop ifNil: [top] ifNotNil: [newTop sender].
  	ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil].
  	[ctxt isNil] whileFalse: [
  		(ctxt tempAt: 2) ifNil: [
  			ctxt tempAt: 2 put: true.
  			unwindBlock := ctxt tempAt: 1.
  			top := unwindBlock asContextWithSender: ctxt.
  			self complete: top to: top].
+ 		ctxt := ctxt findNextUnwindContextUpTo: nil]
+ 	]!
- 		ctxt := ctxt findNextUnwindContextUpTo: nil]!



More information about the Squeak-dev mailing list