[squeak-dev] Re: [Pharo-project] #ensure: issues
Andreas Raab
andreas.raab at gmx.de
Thu Mar 4 01:07:26 UTC 2010
What do you guys think about this? It behaves no worse than the current
implementation if it encountered a problematic ensure: block in
#terminate but it does try to complete one when it finds it. I think
that short of changing the overall terminate semantics this is pretty
close to as good as it gets. The test illustrates the problem.
Eliot - could you check that my usage of findContextSuchThat / closures
/ runUntilErrorOrReturn: looks reasonable? I'm still relatively new to
closure land in these areas.
Cheers,
- Andreas
-------------- next part --------------
'From Squeak3.11alpha of 3 March 2010 [latest update: #9572] on 3 March 2010 at 5:01:04 pm'!
!ProcessTerminateBug methodsFor: 'tests' stamp: 'ar 3/3/2010 17:00'!
testTerminationDuringUnwind
"An illustration of the issue of process termination during unwind"
| unwindStarted unwindFinished p |
unwindStarted := unwindFinished := false.
p := [[] ensure:[
unwindStarted := true.
Processor activeProcess suspend.
unwindFinished := true.
]] fork.
self deny: unwindStarted.
Processor yield.
self assert: unwindStarted.
self deny: unwindFinished.
p terminate.
self assert: unwindFinished.
! !
-------------- next part --------------
'From Squeak3.11alpha of 3 March 2010 [latest update: #9572] on 3 March 2010 at 5:02:58 pm'!
!Process methodsFor: 'changing process state' stamp: 'ar 3/3/2010 17:02'!
terminate
"Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
| ctxt unwindBlock oldList |
self isActiveProcess ifTrue: [
ctxt := thisContext.
[ ctxt := ctxt findNextUnwindContextUpTo: nil.
ctxt isNil
] whileFalse: [
(ctxt tempAt: 2) ifNil:[
ctxt tempAt: 2 put: nil.
unwindBlock := ctxt tempAt: 1.
thisContext terminateTo: ctxt.
unwindBlock value].
].
thisContext terminateTo: nil.
self suspend.
] ifFalse:[
"Always suspend the process first so it doesn't accidentally get woken up"
oldList := self suspend.
suspendedContext ifNotNil:[
"Figure out if we are terminating the process while waiting in Semaphore>>critical:
In this case, pop the suspendedContext so that we leave the ensure: block inside
Semaphore>>critical: without signaling the semaphore."
(oldList class == Semaphore and:[
suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[
suspendedContext := suspendedContext home.
].
"If we are terminating a process halfways through an unwind, try
to complete that unwind block first."
(suspendedContext findNextUnwindContextUpTo: nil) ifNotNil:[:outer|
(suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil:[:inner|
"This is an unwind block currently under evaluation"
suspendedContext runUntilErrorOrReturnFrom: inner.
].
].
ctxt := self popTo: suspendedContext bottomContext.
ctxt == suspendedContext bottomContext ifFalse: [
self debug: ctxt title: 'Unwind error during termination']].
].
! !
More information about the Squeak-dev
mailing list
|