[squeak-dev] order of ensure: processing vs. error handling

Levente Uzonyi leves at caesar.elte.hu
Mon Sep 5 20:49:59 UTC 2016

Exactly. The error handler will add a new frame on top of the stack to 
handle the error, but #ensure: will only evaluate its argument block when 
its receiver block has been executed.

When the error occurs, #ensure:'s receiver block's frame will be on the 
stack, somewhere below the error handler block's frame, hence #ensure:'s 
argument block's evaluation will not have been started at that time.

@Chris: If I were you, I wouldn't bother with such magic. Instead, I'd use 
a linear approach:

| isTheFileOpen |
isTheFileOpen := false.
[ try the first method. isTheFileOpen := true ] ifError: [].
isTheFileOpen ifFalse: [
 	[ try the second method. isTheFileOpen := true ] ifError: [].
 	isTheFileOpen ifFalse: [
 		[ try the third method. isTheFileOpen := true ] ifError: [].
 		... ] ].


On Mon, 5 Sep 2016, Andres Valloud wrote:

> I'd think the ensure blocks haven't run yet because the return: messages sent 
> to the exceptions haven't finished, so exception handling hasn't had a chance 
> to unwind the stack yet.  If I understand things right, what you are seeing 
> is the expected behavior --- because e.g. nobody knows whether an exception 
> handler might fix something (or retry, or...) and resume past the exception 
> instead of aborting the block.
> On 9/5/16 12:30 , Chris Muller wrote:
>> Hi all, I have some in this code in which I try to read a file and, if
>> it fails, try to read it in a different way.
>> But the order of processing ensure: blocks vs. error-handler blocks is
>> not what I expected.  I expected the ensure: block of the inner
>> handler to run before the outer handler.
>> Here's a simple workspace to demonstrate. The temp var "open"
>> represents the status of a FileStream.
>> |open| open:=nil.
>> World findATranscript: nil  Transcript clear.
>> [ [ [ "try method1"  open:=true.  Error signal] ensure: [ open:=false] ]
>>     on: Error
>>     do:
>>         [ : innerErr |   "try method2, but file still open!"
>>         Transcript cr; show: 'innerErr handler, open is ', open asString.
>>         innerErr return:
>>             ([ open:=true.
>>             Error signal ] ensure: [ open:=false ]) ] ]
>>     on: Error
>>     do: [ : outerErr | Transcript cr; show: 'outerErr handler, open is
>> ', open asString ].
>> Transcript cr; show: 'Done.  open is ', open asString.
>> It seems none of the ensure blocks are processed until after ALL the
>> error-handler blocks.  So if a #fileNamed:do: deep deep in the stack
>> encounters an Error, the file is still open in the upper-level
>> handlers, with no good way to close it..

More information about the Squeak-dev mailing list