Login  Register

Finalization question

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options Options
Embed post
Permalink
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Finalization question

Udo Schneider
667 posts
All,

I just stumbled over something which thought was pretty easy - turned
out it isn't as easy as I thought or I'm simply _______ (fill in
expression of choice like "too dumb", "blind", etc.)

I have an object which starts a background process to do it's job. This
object holds a reference to the running proccess in an instance variable.

My goal is to #terminate that proccess once the object isn't needed
anymore (before GC).

Using WeakRegistry for the object itself doesn't work. E.g.

MyObject>>#initialize
        super initialize.
        WeakRegistry default register: self.
        myProcess := self startProcess.

MyObject>>#finalize
        myProcess terminate. "Doesn't work. myProcess is already nil"

I think this is due to all the ivars of the object already being nil
when #finalize is begin called. As far as I read the code this is due to
Object>>#executor returning a shallow copy of the object and thus being
by intention ...

So how to proceed? Did I miss something obvious? Is overwriting
#executor the way to go (in terms of "does it work" and "doesn't it
break something")?

Best Regards,

Udo




Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Ben Coman
5447 posts
Udo Schneider wrote:

> All,
>
> I just stumbled over something which thought was pretty easy - turned
> out it isn't as easy as I thought or I'm simply _______ (fill in
> expression of choice like "too dumb", "blind", etc.)
>
> I have an object which starts a background process to do it's job.
> This object holds a reference to the running proccess in an instance
> variable.
>
> My goal is to #terminate that proccess once the object isn't needed
> anymore (before GC).
>
> Using WeakRegistry for the object itself doesn't work. E.g.
>
> MyObject>>#initialize
>     super initialize.
>     WeakRegistry default register: self.
>     myProcess := self startProcess.
>
> MyObject>>#finalize
>     myProcess terminate. "Doesn't work. myProcess is already nil"
>
> I think this is due to all the ivars of the object already being nil
> when #finalize is begin called. As far as I read the code this is due
> to Object>>#executor returning a shallow copy of the object and thus
> being by intention ...
>
> So how to proceed? Did I miss something obvious? Is overwriting
> #executor the way to go (in terms of "does it work" and "doesn't it
> break something")?
>
> Best Regards,
>
> Udo
>
>
>
>
>

I don't know much about finalization of Weak constructs, but maybe an
alternative.  I assume you have something like..
startProcess
    [    
        "do stuff"  
    ] fork.

so how about...
startProcess
    [ [
        "do stuff"
         myProcess = nil.
    ] whileFalse ] fork.

cheers -ben

Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Udo Schneider
667 posts
On 02.08.2014 15:33, Ben Coman wrote:

> I don't know much about finalization of Weak constructs, but maybe an
> alternative.  I assume you have something like..
> startProcess
>     [        "do stuff"    ] fork.
>
> so how about...
> startProcess
>     [ [
>         "do stuff"
>          myProcess = nil.
>     ] whileFalse ] fork.
>
> cheers -ben
>
>
That's a clever way to do it ... only it doesn't work :-(

My current understanding is that "self" in the block refers to the
original instance where "myProcess" is still assigned. "self" in
#finalize is the "executor" object which is (by default) a #shallowCopy
of the object where ivar are nil.

I currently have the feeling I'm missing something. Finalization
shouldn't be that hard ... or may I'm simply spoiled comming from a
Dolphin Smalltalk background :-)

Thanks for your help,

Udo



Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

stepharo
5159 posts
In reply to this post by Udo Schneider
We should write a chapter on finalization but since I do not know it
well (and I forget)...
igor will answer you.

Stef
On 2/8/14 13:16, Udo Schneider wrote:

> All,
>
> I just stumbled over something which thought was pretty easy - turned
> out it isn't as easy as I thought or I'm simply _______ (fill in
> expression of choice like "too dumb", "blind", etc.)
>
> I have an object which starts a background process to do it's job.
> This object holds a reference to the running proccess in an instance
> variable.
>
> My goal is to #terminate that proccess once the object isn't needed
> anymore (before GC).
>
> Using WeakRegistry for the object itself doesn't work. E.g.
>
> MyObject>>#initialize
>     super initialize.
>     WeakRegistry default register: self.
>     myProcess := self startProcess.
>
> MyObject>>#finalize
>     myProcess terminate. "Doesn't work. myProcess is already nil"
>
> I think this is due to all the ivars of the object already being nil
> when #finalize is begin called. As far as I read the code this is due
> to Object>>#executor returning a shallow copy of the object and thus
> being by intention ...
>
> So how to proceed? Did I miss something obvious? Is overwriting
> #executor the way to go (in terms of "does it work" and "doesn't it
> break something")?
>
> Best Regards,
>
> Udo
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Udo Schneider
667 posts
On 04.08.2014 21:35, stepharo wrote:> We should write a chapter on
finalization but since I do not know it
 > well (and I forget)...
 > igor will answer you.
 >
 > Stef

I found "the" bug. It seems it's a side effect of finalization,
WeakRegistry and cyclic references. I'll write a TestCase for that.

Thanks,

Udo




Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Santiago Bragagnolo
219 posts
TaskIT has a feature named StickyReference, for that propouse, is not trivial at all, because when you fork you are using a block that has a reference to a context. In the end even if your variable is nil, your process is being pointed by the context. 

What i did in TaskIT is to have a witness object, that mixed with a ghost proxy (the one you will be pointing) can do the magic. 
If what you want in your process variable is not really a reference to the process or if you have enough with a partial proxy based in DNU, things can go easier, you just need to register that third object into the weak resgistry.


If you check out taskit commit 20 you will find a mechanism based in a DNU based proxy. If you checkout the last stable version you will  find the witness/ghost proxy based one. In any case, look for the method asStickyReference. It will lead you straight to the mechanism. 


Gofer new 
smalltalkhubUser: 'CAR' project: 'TaskIT';
configuration;
load.

(#ConfigurationOfTaskIT asClass project version: #stable) load: 'full'







2014-08-05 11:22 GMT+02:00 Udo Schneider <[hidden email]>:
On <a href="tel:04.08.2014%2021" value="+33408201421" target="_blank">04.08.2014 21:35, stepharo wrote:> We should write a chapter on finalization but since I do not know it

> well (and I forget)...
> igor will answer you.
>
> Stef

I found "the" bug. It seems it's a side effect of finalization, WeakRegistry and cyclic references. I'll write a TestCase for that.

Thanks,

Udo





Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Udo Schneider
667 posts
On 05.08.2014 12:10, Santiago Bragagnolo wrote:> TaskIT has a feature
named StickyReference, for that propouse, is not
 > trivial at all, because when you fork you are using a block that has a
 > reference to a context. In the end even if your variable is nil, your
 > process is being pointed by the context.
You're feeding my deepest fears :-)

I also reduced the testcases to even show a (IMHO) faulty behavior w/o
any process at all. Simple references are sufficient.

Still I'm wondering what's the official way to solve that problem. IMHO
objects with forked background processes which want to terminate those
processes implicitly using finalization isn't something uncommon ...

CU,

Udo




Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Udo Schneider
667 posts
On 05.08.2014 14:08, Udo Schneider wrote:
> I also reduced the testcases to even show a (IMHO) faulty behavior w/o
> any process at all. Simple references are sufficient.
I just created a small TestCase showing the (IHMO) faulty behavior. I
hope the intention is clear from the package/var names.

Gofer it
        smalltalkhubUser: 'UdoSchneider' project: 'Playground';
        package: 'CyclicFinalizationBug';
        load.

Check out the tests in CyclicFinalizationBugTestCase.

Hope this helps.

CU,

Udo



Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Ben Coman
5447 posts
Udo Schneider wrote:

> On 05.08.2014 14:08, Udo Schneider wrote:
>> I also reduced the testcases to even show a (IMHO) faulty behavior w/o
>> any process at all. Simple references are sufficient.
> I just created a small TestCase showing the (IHMO) faulty behavior. I
> hope the intention is clear from the package/var names.
>
> Gofer it
>     smalltalkhubUser: 'UdoSchneider' project: 'Playground';
>     package: 'CyclicFinalizationBug';
>     load.
>
> Check out the tests in CyclicFinalizationBugTestCase.
>
> Hope this helps.
>
> CU,
>
> Udo
>
>
>
>
Is there a Fogbugz case to track it?
cheers -ben

Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Finalization question

Udo Schneider
667 posts
On 06.08.2014 02:36, Ben Coman wrote:
> Is there a Fogbugz case to track it?
> cheers -ben

There is now:
https://pharo.fogbugz.com/f/cases/13785/Cyclic-Referencing-self-prevents-an-object-from-being-finalized

CU,

Udo