[squeak-dev] Re: [Pharo-project] #ensure: issues

Igor Stasenko siguctua at gmail.com
Thu Mar 4 01:18:04 UTC 2010

On 4 March 2010 02:34, Eliot Miranda <eliot.miranda at gmail.com> wrote:
> 2010/3/3 Andreas Raab <andreas.raab at gmx.de>
>> On 3/3/2010 2:07 PM, Levente Uzonyi wrote:
>>> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>>>> i don't get it. Just before that, you said: ' I'd expect it to be
>>>> evaluated no matter what happens.' ?
>>>> But now you saying that it may not be executed in some conditions
>>>> (when user pressing abandon button, causing process to be terminated).
>>> It's simple: don't terminate process X from another process if process X
>>> is executing a termiation block (aka #ensure: block). Or if you
>>> terminate it, make sure that the execution of the block will continue
>>> somehow (I don't care how).
>> You're missing Igors point which is that in his example the halt /
>> Transcript *was* in the ensure block and as a result you're contradicting
>> yourself here. Let's go back to Igor's example:
>> [self boom ] ensure: [ self halt. Transcript show: 'boom']
>> The halt is inside the ensure block. If you terminate the process from the
>> debugger, it would be logical from your statement that the Transcript
>> message would be executed - after all it's " executing a termiation block
>> (aka #ensure: block)" and so it can't be terminated by your reasoning.
>> However, when Igor was pointing this out you replied with "I didn't say
>> that. I said evaluate it the same way as normal code." which is inconsistent
>> with the other statement.
>>> I think every user of #ensure: expects that the termination blocks are
>>> executed even if the process which is executing the receiver of #ensure:
>>> is terminated. And it actually happens in all but this case.
>> The question of terminating processes is always tricky. I don't think that
>> your proposal would actually work in practice - it could easily result in
>> processes that cannot be terminated due to a simple bug in an ensure block.
>> Personally, I'd rather say that the more useful behavior would be something
>> along the lines of saying that process termination either skips the current
>> ensure block (assuming there's a bug and it should get the heck out of it
>> but try to evaluate the remaining ones) or that there need to be two
>> terminations - one that is 'soft' and won't allow ensure blocks to be
>> skipped and one that is 'hard' (kill -9 hard) and just ignores all the
>> ensure blocks.
> That's what we did in VisualWorks.  Normal terminate is as you say.  It
> tries to run unwinds until an error, and then if necessary one wields
> terminateWithExtremePrejudice and kills the thing stone dead.

Its easy to follow that road, since its cheap and looks like logical
choice: add another layer on top of existing one,
to ensure correct (or stable) behavior.
But i would say, that given solution is as good as it costs :)
The fact is, that to terminate the process is "safe" way, you have to
run the code. And once you running a code, it means that someone may
want to terminate it. So, there are no guarantees that nobody else
wouldn't want to terminate your code which 'terminates' some process.
So, its and endless loop.. Lets write a code to ensure that
termination code runs to an end, termination termination code runs to
end and so on...
A solution lies on the surface: do not run any code on termination. Period.
Then, consequently, change the concept: do not expect that any bit of
code will have chances to run, and hence, remove the #ensure: from
use. Too bad, it is too late to go that way, since we having #ensure:
blocks used everywhere.

The main use of #ensure: block is to keep things in a consistent
state, regardless of what is happens inside receiver block:
[ self goneWild ] ensure: [ self becomeSaneAgain ]

Not sure for all, but i think for most of the cases, one could use a
transaction-like approach:

| copy |
copy := self copy.
copy goneWild.
copy isEveryThingOK ifTrue: [ self become: copy ] ifFalse: [ "do nothing" ]

the concept is simple: make a backups before doing risky things. In
this way, you always having an easy way to get back to consistent
state, despite what was the outcome of intended operation.

But of course, i realizing that its too late to change that :)

>> Cheers,
>>  - Andreas

Best regards,
Igor Stasenko AKA sig.

More information about the Squeak-dev mailing list