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

Levente Uzonyi leves at elte.hu
Thu Mar 4 01:44:02 UTC 2010


On Thu, 4 Mar 2010, Igor Stasenko wrote:

> 2010/3/4 Levente Uzonyi <leves at elte.hu>:
>> On Thu, 4 Mar 2010, Igor Stasenko wrote:
>>
>>> On 4 March 2010 01:56, Nicolas Cellier
>>> <nicolas.cellier.aka.nice at gmail.com> wrote:
>>>>
>>>> 2010/3/4 Levente Uzonyi <leves at elte.hu>:
>>>>>
>>>>> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>>>>>
>>>>>> 2010/3/3 Levente Uzonyi <leves at elte.hu>:
>>>>>>>
>>>>>>> On Wed, 3 Mar 2010, Andreas Raab wrote:
>>>>>>>
>>>>>>>> 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.
>>>>>>>
>>>>>>> That shows my lack of knowledge about how the debugger works.
>>>>>>>
>>>>>>>>
>>>>>>>>> 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.
>>>>>>>
>>>>>>> I'm only saying that normal usage (aka #terminate) shouldn't do
>>>>>>> unexpected
>>>>>>> things like this.
>>>>>>> If you read the comment of Process >> #terminate, you may assume that
>>>>>>> #ensure: and #ifCurtailed: blocks will be excuted even if you use
>>>>>>> #terminate, but that's not true.
>>>>>>>
>>>>>>> "Stop the process that the receiver represents forever.  Unwind to
>>>>>>> execute
>>>>>>> pending ensure:/ifCurtailed: blocks before terminating."
>>>>>>>
>>>>>>>
>>>>>>> Levente
>>>>>>>
>>>>>>
>>>>>> The only way I see to solve your problem would be to execute the
>>>>>> unwind block in another process...
>>>>>> Quite technical and costly !
>>>>>
>>>>> It's our problem. Just look at the senders of #ensure: and imagine what
>>>>> will
>>>>> happen if the termination block is not evaluated.
>>>>> I think there's another way (though it might be my lack of knowledge
>>>>> again).
>>>>> After suspending the process which is about to be terminated we can
>>>>> check if
>>>>> it's executing a termination block. It it's not, we are safe to continue
>>>>> the
>>>>> termination, otherwise we can do something else which ensures that the
>>>>> termination block is evaluated.
>>>>>
>>>>
>>>> Maybe...
>>>> Unfortunately, you did not tell how you will distinguish well behaved
>>>> unwind-blocks from Igor's example...
>>>>
>>>
>>> Yes, then what prevents me from writing:
>>>
>>> [ [ ] ensure: [ self doCrazyThings ] ] fork.
>>
>> What prevents you from writing: Object superclass: Object. ?
>> Nothing, but you don't do that, do you?
>>
> So, why at all, you care about using #ensure: then? If you putting
> everything up to the hands of developer,
> then obviously you won't need to use this message, because you always
> know that you're running a reliable code which
> will always let you to run your things in the end. :)
>
>>>
>>> and now given assumption that any code which placed inside ensure
>>> block should always run to the end, without chances being terminated,
>>> will have ill side effects.
>>
>> You can terminate it (maybe not the usual way).
>>
> that's the point. Why do we need two (or more) ways to terminate a process?
>
>>> The #ensure: means, that interpreter will have a chance to enter that
>>> block eventually, but it should not mean that it will keep running the
>>> code there until normal or non-local return from that block.
>>
>> Then it doesn't ensure anything at all, so it should be called
>> #tryToEvaluateThisToo:.
>>
> in fact, this is the actual behavior :)
> If i press the power button on your PC, or plug out the power cord,
> any #ensure: blocks will have no chances to run either way.
> So, relying on something, which is not reliable is a fallacy :)

Here's a simple example (replace file with any external resource):
My process opened a file, a termination block will close it if it's 
evaluated. If I send #terminate to the process I expect my file to be 
closed, so I won't leak a file descriptor.
If the file can't be closed (aka the termination block raised an 
error) then there's a serious problem. It doesn't really matter what 
happens then.

But I don't have to try to convince you anymore, because Andreas is about 
to solve the issue.


Levente

>
>>
>> Levente
>>
>>> Othewise, you losing a way to terminate unwanted, ill-behaved process.
>>>
>>>> Nicolas
>>>>
>>>>>
>>>>> Levente
>>>>>
>>>>>>
>>>>>> Nicolas
>>>>>>
>>>>>>>>
>>>>>>>> Cheers,
>>>>>>>>  - Andreas
>>>>>>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>
>>
>>
>>
>>
>
>
>
> -- 
> Best regards,
> Igor Stasenko AKA sig.
>
>


More information about the Squeak-dev mailing list