I keep getting a walkback after saving and quitting. Here is the log file. I'm running 3.2 #4904 on a Windows 3.2.2 May 26 2002 release.
Error: Attempt to evaluate a block that is already being evaluated. 30 June 2002 6:10 pm
VM: Win32 - Squeak3.2gamma of 12 January 2002 [latest update: #4879] Image: Squeak3.2gamma [latest update: #4904]
BlockContext(Object)>>error: Receiver: [] in Semaphore>>critical: Arguments and temporary variables: t1: 'Attempt to evaluate a block that is already being evaluated.' Receiver's instance variables: sender: BlockContext>>ensure: pc: 37 stackp: 1 nargs: 0 startpc: 35 home: Semaphore>>critical:
BlockContext>>valueWithArguments: Receiver: [] in Semaphore>>critical: Arguments and temporary variables: t1: #() Receiver's instance variables: sender: BlockContext>>ensure: pc: 37 stackp: 1 nargs: 0 startpc: 35 home: Semaphore>>critical:
BlockContext>>value Receiver: [] in Semaphore>>critical: Arguments and temporary variables:
Receiver's instance variables: sender: BlockContext>>ensure: pc: 37 stackp: 1 nargs: 0 startpc: 35 home: Semaphore>>critical:
BlockContext(ContextPart)>>unwindTo: Receiver: [] in Semaphore>>critical: Arguments and temporary variables: t1: nil t2: BlockContext>>ensure: t3: nil t4: [] in Semaphore>>critical: Receiver's instance variables: sender: BlockContext>>ensure: pc: 37 stackp: 1 nargs: 0 startpc: 35 home: Semaphore>>critical:
--- The rest of the stack --- Process>>terminate ProcessorScheduler class>>startUp ProcessorScheduler class(Behavior)>>startUp: [] in SystemDictionary>>send:toClassesNamedIn:with: OrderedCollection>>do: SystemDictionary>>send:toClassesNamedIn:with: SystemDictionary>>processStartUpList: SystemDictionary>>snapshot:andQuit:embedded: SystemDictionary>>snapshot:andQuit: TheWorldMenu>>saveAndQuit TheWorldMenu>>doMenuItem:with: [] in MenuItemMorph>>invokeWithEvent: BlockContext>>ensure: CursorWithMask(Cursor)>>showWhile: MenuItemMorph>>invokeWithEvent: MenuItemMorph>>mouseUp: MenuItemMorph>>handleMouseUp: MouseButtonEvent>>sentTo: MenuItemMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>dispatchEvent:with: MenuItemMorph(Morph)>>processEvent:using: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>dispatchEvent:with: MenuMorph(Morph)>>processEvent:using: MenuMorph(Morph)>>processEvent: MenuMorph>>handleFocusEvent: [] in HandMorph>>sendFocusEvent:to:clear: PasteUpMorph>>becomeActiveDuring: HandMorph>>sendFocusEvent:to:clear: HandMorph>>sendEvent:focus:clear: HandMorph>>sendMouseEvent: HandMorph>>handleEvent: HandMorph>>processEvents [] in WorldState>>doOneCycleNowFor: Array(SequenceableCollection)>>do: WorldState>>handsDo: WorldState>>doOneCycleNowFor: WorldState>>doOneCycleFor: PasteUpMorph>>doOneCycle [] in Project class>>spawnNewProcess [] in BlockContext>>newProcess
Hi,
Just a question: Does anyone know what the *expected* behavior for terminating a process is where an unwind block is currently under evaluation?! E.g., a simple test case is:
process := [[3+4] ensure:[ Transcript cr; show: 'Unwinding...'. Processor activeProcess suspend. Transcript show:'done'. ]] fork. (Delay forMilliseconds: 100) wait. process terminate.
Right now this raises an error in Squeak (attempting to evaluate a block which is already evaluated) so this is clearly wrong. But what *is* the expected behavior in this case?! Does somebody know what ANSI has to say about this problem?
Cheers, - Andreas
ANSI doesn't say anything about this because it doesn't talk about processes. However, if it had covered this, it would have said something like:
"If the current state of a Process that is explicitly terminated includes any block activations with terminationBlocks then the terminationBlocks will be executed in the reverse of the order in which their corresponding receiver blocks were evaluated. Explicitly terminating a process whose termination processing has already been initiated has no effect upon the terminating process."
Basically, when a process is terminated it's stack should be unwound and any unwind blocks associated with active blocks should be executed. The problem you describe seems to reflect a bug in the Squeak implementation of ensure. An ensure block is supposed to execute after the activation of the block it "protects" has been discarded. In other words, before execution of the ensure block begins the stack should be trimmed back to just before the protected activation and any mechanism for triggering subsequent execution of the ensure blocks should be eliminated. Then the actual activation of the ensure block is just a normal block activation, there is nothing special about it.
It sounds like the squeak implementation is not cleaning up before activating the ensure block. The terminate should find neither the protected block nor a pending ensure block. All it should see is a normal, unprotected block activation. The bug might be related to Squeak's lack of closures, as closures certainly simplify the implementation of ensure/ifCurtailed.
Allen_Wirfs-Brock@Instantiations.com
At 08:01 PM 6/30/2002 +0200, Andreas Raab wrote:
Hi,
Just a question: Does anyone know what the *expected* behavior for terminating a process is where an unwind block is currently under evaluation?! E.g., a simple test case is:
process := [[3+4] ensure:[ Transcript cr; show: 'Unwinding...'. Processor activeProcess suspend. Transcript show:'done'. ]] fork. (Delay forMilliseconds: 100) wait. process terminate.
Right now this raises an error in Squeak (attempting to evaluate a block which is already evaluated) so this is clearly wrong. But what *is* the expected behavior in this case?! Does somebody know what ANSI has to say about this problem?
Cheers,
- Andreas
Don't know about ANSI, but I would expect the process to be terminated before "Transcript show: 'done'" gets executed, and any ensure (or ifCurtailed) blocks above this method to be executed (probably in the process that calls #terminate).
Looking at BlockContext>>ensure:, it looks like your bug might be fixed by niling out aBlock before executing it (which would require that you access thisContext). Or, perhaps a better way is to add a new <primitive: 81> method to BlockContext that simply does nothing if the primitive fails...call it BlockContext>>#valueForUnwind, then make ContextPart>>unwindTo: use that method.
If you fix that bug, then it looks to me like it would do the expected thing.
- Stephen
-----Original Message----- From: squeak-dev-admin@lists.squeakfoundation.org [mailto:squeak-dev-admin@lists.squeakfoundation.org] On Behalf Of Andreas Raab Sent: Sunday, June 30, 2002 2:02 PM To: squeak-dev@lists.squeakfoundation.org Subject: unwind behavior
Hi,
Just a question: Does anyone know what the *expected* behavior for terminating a process is where an unwind block is currently under evaluation?! E.g., a simple test case is:
process := [[3+4] ensure:[ Transcript cr; show: 'Unwinding...'. Processor activeProcess suspend. Transcript show:'done'. ]] fork. (Delay forMilliseconds: 100) wait. process terminate.
Right now this raises an error in Squeak (attempting to evaluate a block which is already evaluated) so this is clearly wrong. But what *is* the expected behavior in this case?! Does somebody know what ANSI has to say about this problem?
Cheers,
- Andreas
squeak-dev@lists.squeakfoundation.org