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

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
51 messages Options
123
Reply | Threaded
Open this post in threaded view
|

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

Levente Uzonyi-2
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?


Cheers,
Balázs & Levente


>
> *yay
> Henry*
> *
>

Reply | Threaded
Open this post in threaded view
|

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

Igor Stasenko
2010/3/2 Levente Uzonyi <[hidden email]>:

> 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.


> Cheers,
> Balázs & Levente
>
>
>>
>> *yay
>> Henry*
>> *
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

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

Levente Uzonyi-2
On Tue, 2 Mar 2010, Igor Stasenko wrote:

> 2010/3/2 Levente Uzonyi <[hidden email]>:
> 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.


Levente


> Cheers,
> Balázs & Levente
>
>
>>
>> *yay
>> Henry*
>> *
>
>
>
>


--
Best regards,
Igor Stasenko AKA sig.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply | Threaded
Open this post in threaded view
|

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

Igor Stasenko
2010/3/3 Levente Uzonyi <[hidden email]>:

> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>
>> 2010/3/2 Levente Uzonyi <[hidden email]>:
>> 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']


>
> Levente
>
>
>> Cheers,
>> Balázs & Levente
>>
>>
>>>
>>> *yay
>>> Henry*
>>> *
>>
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

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

Levente Uzonyi-2
On Wed, 3 Mar 2010, Igor Stasenko wrote:

> 2010/3/3 Levente Uzonyi <[hidden email]>:
>> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>>
>>> 2010/3/2 Levente Uzonyi <[hidden email]>:
>>> 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.


Levente

>
>
>>
>> Levente
>>
>>
>>> Cheers,
>>> Balázs & Levente
>>>
>>>
>>>>
>>>> *yay
>>>> Henry*
>>>> *
>>>
>>>
>>>
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>

Reply | Threaded
Open this post in threaded view
|

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

Igor Stasenko
2010/3/3 Levente Uzonyi <[hidden email]>:

> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>
>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>
>>> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>>>
>>>> 2010/3/2 Levente Uzonyi <[hidden email]>:
>>>> 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?

>
> Levente
>
>>
>>
>>>
>>> Levente
>>>
>>>




--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

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

Levente Uzonyi-2
On Wed, 3 Mar 2010, Igor Stasenko wrote:

> 2010/3/3 Levente Uzonyi <[hidden email]>:
>> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>>
>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>
>>>> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>>>>
>>>>> 2010/3/2 Levente Uzonyi <[hidden email]>:
>>>>> 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.
>
>

Reply | Threaded
Open this post in threaded view
|

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

Igor Stasenko
2010/3/3 Levente Uzonyi <[hidden email]>:

> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>
>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>
>>> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>>>
>>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>>
>>>>> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>>>>>
>>>>>> 2010/3/2 Levente Uzonyi <[hidden email]>:
>>>>>> 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.

Please define, what is 'normal' code. If you maybe know, exceptions
and stack unwinding implemented in smalltalk, there's no any 'magic'
and this code interpreted by VM as any other code, which makes it as
'normal' as any other one.

> If you evaluate this code:
>
> self halt. Transcript show: 'boom'.
>
> and press abandon, then Transcript show: 'boom' will not be executed.
>

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).

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



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

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

Levente Uzonyi-2
On Wed, 3 Mar 2010, Igor Stasenko wrote:

> 2010/3/3 Levente Uzonyi <[hidden email]>:
>> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>>
>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>
>>>> On Wed, 3 Mar 2010, Igor Stasenko wrote:
>>>>
>>>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>>>
>>>>>> On Tue, 2 Mar 2010, Igor Stasenko wrote:
>>>>>>
>>>>>>> 2010/3/2 Levente Uzonyi <[hidden email]>:
>>>>>>> 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.
>
> Please define, what is 'normal' code. If you maybe know, exceptions
> and stack unwinding implemented in smalltalk, there's no any 'magic'
> and this code interpreted by VM as any other code, which makes it as
> 'normal' as any other one.
>
>> If you evaluate this code:
>>
>> self halt. Transcript show: 'boom'.
>>
>> and press abandon, then Transcript show: 'boom' will not be executed.
>>
>
> 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).
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.


Levente

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

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Andreas.Raab
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.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Levente Uzonyi-2
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

>
> Cheers,
>  - Andreas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Nicolas Cellier
2010/3/3 Levente Uzonyi <[hidden email]>:

> 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 !

Nicolas

>>
>> Cheers,
>>  - Andreas
>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Levente Uzonyi-2
On Thu, 4 Mar 2010, Nicolas Cellier wrote:

> 2010/3/3 Levente Uzonyi <[hidden email]>:
>> 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.


Levente

>
> Nicolas
>
>>>
>>> Cheers,
>>>  - Andreas
>>>
>>>
>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Nicolas Cellier
2010/3/4 Levente Uzonyi <[hidden email]>:

> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>
>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>
>>> 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...

Nicolas

>
> Levente
>
>>
>> Nicolas
>>
>>>>
>>>> Cheers,
>>>>  - Andreas
>>>>
>>>>
>>>
>>>
>>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Levente Uzonyi-2
On Thu, 4 Mar 2010, Nicolas Cellier wrote:

> 2010/3/4 Levente Uzonyi <[hidden email]>:
>> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>>
>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>
>>>> 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...
I'd give the responsibility to the developer to write termination blocks
which are safe to evaluate. So I assume that all such blocks behave well.
If something goes wrong you can kill the process with a more aggressive
method (as Andreas suggested), but you lose the guarantee that the current
termination block will be evaluated.


Levente

>
> Nicolas
>
>>
>> Levente
>>
>>>
>>> Nicolas
>>>
>>>>>
>>>>> Cheers,
>>>>>  - Andreas
>>>>>
>>>>>
>>>>
>>>>
>>>
>>
>>
>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Igor Stasenko
In reply to this post by Nicolas Cellier
On 4 March 2010 01:56, Nicolas Cellier
<[hidden email]> wrote:

> 2010/3/4 Levente Uzonyi <[hidden email]>:
>> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>>
>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>
>>>> 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.

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.
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.
Othewise, you losing a way to terminate unwanted, ill-behaved process.

> Nicolas
>
>>
>> Levente
>>
>>>
>>> Nicolas
>>>
>>>>>
>>>>> Cheers,
>>>>>  - Andreas
>>>>>

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Nicolas Cellier
In reply to this post by Levente Uzonyi-2
2010/3/4 Levente Uzonyi <[hidden email]>:

> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>
>> 2010/3/4 Levente Uzonyi <[hidden email]>:
>>>
>>> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>>>
>>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>>
>>>>> 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...
>
> I'd give the responsibility to the developer to write termination blocks
> which are safe to evaluate. So I assume that all such blocks behave well. If
> something goes wrong you can kill the process with a more aggressive
> method (as Andreas suggested), but you lose the guarantee that the current
> termination block will be evaluated.
>
>
> Levente
>

I would tend to focus first on the senders of terminate since
terminating is unsafe...
How many of them would deserve to be transformed in a terminateRequest ?

Nicolas

>>
>> Nicolas
>>
>>>
>>> Levente
>>>
>>>>
>>>> Nicolas
>>>>
>>>>>>
>>>>>> Cheers,
>>>>>>  - Andreas
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>>
>>>
>>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Eliot Miranda-2
In reply to this post by Andreas.Raab


2010/3/3 Andreas Raab <[hidden email]>
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.


Cheers,
 - Andreas




Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Levente Uzonyi-2
In reply to this post by Nicolas Cellier
On Thu, 4 Mar 2010, Nicolas Cellier wrote:

> 2010/3/4 Levente Uzonyi <[hidden email]>:
>> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>>
>>> 2010/3/4 Levente Uzonyi <[hidden email]>:
>>>>
>>>> On Thu, 4 Mar 2010, Nicolas Cellier wrote:
>>>>
>>>>> 2010/3/3 Levente Uzonyi <[hidden email]>:
>>>>>>
>>>>>> 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...
>>
>> I'd give the responsibility to the developer to write termination blocks
>> which are safe to evaluate. So I assume that all such blocks behave well. If
>> something goes wrong you can kill the process with a more aggressive
>> method (as Andreas suggested), but you lose the guarantee that the current
>> termination block will be evaluated.
>>
>>
>> Levente
>>
>
> I would tend to focus first on the senders of terminate since
> terminating is unsafe...
The comment suggest to me that it's safe to use it, because it will
evaluate the termination blocks.


Levente

> How many of them would deserve to be transformed in a terminateRequest ?
>
> Nicolas
>
>>>
>>> Nicolas
>>>
>>>>
>>>> Levente
>>>>
>>>>>
>>>>> Nicolas
>>>>>
>>>>>>>
>>>>>>> Cheers,
>>>>>>>  - Andreas
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>>
>>
>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] #ensure: issues

Nicolas Cellier
In reply to this post by Eliot Miranda-2
2010/3/4 Eliot Miranda <[hidden email]>:

>
>
> 2010/3/3 Andreas Raab <[hidden email]>
>>
>> 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.

Fun name.
I just imagine a terminateWithGradualPrejudice that would step to next
unwind block in case of error...

Nicolas

>>
>> Cheers,
>>  - Andreas
>>
>
>
>
>
>

123