[Pharo-project] [squeak-dev] #ensure: issues (was: Re: Pharo by Example vol 2: new chapter available)

Levente Uzonyi leves at elte.hu
Wed Mar 3 17:24:41 UTC 2010


On Wed, 3 Mar 2010, Igor Stasenko wrote:

> 2010/3/3 Levente Uzonyi <leves at elte.hu>:
>> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>>
>>> 2010/3/3 Levente Uzonyi <leves at elte.hu>:
>>>>
>>>> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>>>>
>>>>> 2010/3/2 Levente Uzonyi <leves at elte.hu>:
>>>>> On Tue, 2 Mar 2010, Henrik Sperre Johansen wrote:
>>>>>
>>>>>>
>>>>>>>> PS. For the not-so-faint-of-heart, open a Transcript and try
>>>>>>>> evaluating:
>>>>>>>> |proc|
>>>>>>>> proc := [[Transcript show: 'Start!'. ] ensure: [Transcript show:
>>>>>>>> 'Finish!' Processor yield.]] newProcess.
>>>>>>>> proc resume.
>>>>>>>> Processor yield.
>>>>>>>> proc suspend.
>>>>>>>> proc terminate.
>>>>>>>
>>>>>>> Why don't we get it printing?
>>>>>>
>>>>>> Forgot a . there, supposed to be
>>>>>>
>>>>>> |proc|
>>>>>> proc := [[Transcript show: 'Start!'. ] ensure: [Transcript show:
>>>>>> 'Finish!'. Processor yield.]] newProcess.
>>>>>> proc resume.
>>>>>> Processor yield.
>>>>>> proc suspend.
>>>>>> proc terminate.
>>>>>>
>>>>>> on my machine it prints:
>>>>>> *Start!Start!Finish!
>>>>>
>>>>> The problem occurs because Transcript >> #endEntry (sent from #show:)
>>>>> takes a while to execute, so the process (proc) prints 'Start!', but
>>>>> it gets terminated before execution reaches #resetContents (#reset in
>>>>> Squeak). So 'Start!' is still in the stream. Then our process executes
>>>>> the
>>>>> #ensure: block and it prints 'Start!' and 'Finish!' too.
>>>>>
>>>>> There's worse problem with #ensure: and #terminate is that, a process
>>>>> executing an #ensure: block can be terminated. If you evaluate this
>>>>> code:
>>>>>
>>>>> | process stage1 stage2 stage3 counter |
>>>>> stage1 := stage2 := stage3 := false.
>>>>> counter := 0.
>>>>> process := [
>>>>>        [ stage1 := true ] ensure: [
>>>>>                stage2 := true.
>>>>>                1000000 timesRepeat: [ counter := counter + 1 ].
>>>>>                stage3 := true ] ] newProcess.
>>>>> process resume.
>>>>> Processor yield.
>>>>> process suspend.
>>>>> process terminate.
>>>>> 1000 milliSeconds asDelay wait.
>>>>> { stage1. stage2. stage3. counter } explore
>>>>>
>>>>> you will find that stage1 and stage2 is reached as expected, but stage3
>>>>> is
>>>>> not and counter is less than 1000000. That's because the forked process
>>>>> started evaluating the #ensure: block, but it was terminated by our
>>>>> process.
>>>>>
>>>>> Is this the expected behavior when sending #terminate to a process which
>>>>> is
>>>>> evaluating an #ensure: block?
>>>>>
>>>>>
>>>> What you think is expected behavior here:
>>>>
>>>> a) process termination should start (be triggered) only when process
>>>> is outside of any #ensure: closure?
>>>> b) #ensure: block should always run to the end, despite anything?
>>>>
>>>> Since you can't predict, what code will run inside ensure block, the
>>>> only guarantee that you having is actually
>>>> that your process will always enters such blocks during the normal
>>>> flow, or exception handling. But there is no guarantees that it will
>>>> be able to run the code inside it, when you terminating it.
>>>>
>>>>
>>>> I'd expect it to be evaluated no matter what happens.
>>>>
>>> even this one?
>>> [self boom ] ensure: [ self halt. Transcript show: 'boom']
>>
>> Yes.
>>
> so, even if you click 'abandon' in debugger popup, its still should
> print 'boom' in transcript?

I didn't say that. I said evaluate it the same way as normal code. If you 
evaluate this code:

self halt. Transcript show: 'boom'.

and press abandon, then Transcript show: 'boom' will not be executed.


Levente

>
>>
>> Levente
>>
>>>
>>>
>>>>
>>>> Levente
>>>>
>>>>
>
>
>
>
> -- 
> Best regards,
> Igor Stasenko AKA sig.
>
>


More information about the Squeak-dev mailing list