[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
|