[squeak-dev] Re: Multiple finalizers per single object

Levente Uzonyi leves at elte.hu
Fri Sep 24 02:07:23 UTC 2010


On Fri, 24 Sep 2010, Igor Stasenko wrote:

> 2010/9/24 Levente Uzonyi <leves at elte.hu>:
>> On Fri, 24 Sep 2010, Igor Stasenko wrote:
>>
>>> On 24 September 2010 01:40, Andreas Raab <andreas.raab at gmx.de> wrote:
>>>>
>>>> On 9/23/2010 3:27 PM, Igor Stasenko wrote:
>>>>>
>>>>> On 23 September 2010 23:58, Andreas Raab<andreas.raab at gmx.de>  wrote:
>>>>>>
>>>>>> Isn't that a bit of a made-up problem? I've never seen (nor heard of)
>>>>>> anyone
>>>>>> even trying to attach more than one finalizer to an object. Disallowing
>>>>>> it
>>>>>> could be done, but unless there's a good reason for it I'm not in favor
>>>>>> of
>>>>>> deciding what is good policy and what isn't without a practical use
>>>>>> case
>>>>>> at
>>>>>> hand. If you have a use-case I'd like to hear more about it, but if
>>>>>> not,
>>>>>> then *shrug*, who cares :-)
>>>>>>
>>>>>
>>>>> The practical use, that one may mistakenly add two same finalizers on
>>>>> a same object,
>>>>> like closing a file handle, or free external memory.
>>>>> And it is potentially dangerous, because OS could reuse the same
>>>>> memory location or file handle,
>>>>> once you closed it, so, by closing it twice you can get a serious
>>>>> trouble finding what's going on.
>>>>>
>>>>> My point, that if one ever needs a composite finalization action, a
>>>>> WeakRegistry is wrong place for that.
>>>>> WeakRegistry should prevent registering more than a signle finalizer
>>>>> per unique object to prevent
>>>>> potential problems which could arise from such composition(s).
>>>>
>>>> So you're saying one *could* do that and *if* one did that it *might*
>>>> lead
>>>> to a *potential* issue? Sounds like solving a non-problem to me :-)
>>>>
>>>
>>> Yes i consider it as a potential security hole. It simply feels wrong to
>>> me.
>>> It is good that nobody using multiple finalizers.
>>
>> How do you know that for sure?
>> Currently our announcement framework uses this feature to remove all weak
>> subscriptions for an object when it's garbage collected. This avoids
>> iterating through all the subscriptions looking for those which don't have a
>> subscriber anymore. I'm sure it could be implemented another way, but it's
>> really simple this way.
>>
> This is userful.
> Though, iterating through all subscriptions, this is what you can
> avoid using new finalization scheme.
>
> When weak field of subscription becomes nil, a subscription will be
> automatically added to the list of expired subscriptions.
> Then, after GC, you simply go through that list and remove them from
> subscriptions container.
> Note that such implementation doesn't involving WeakRegistry at all,
> and therefore you won't be needing
> multiple finalizers per single object.  :)

I think we can live without multiple finalizers per object.
Maybe the best solution is to make the behavior changeable when an object 
already has a finalizer in a WeakRegistry. With the current WeakRegistry 
this could be something like:

WeakRegistry >> add: anObject executor: anExecutor
 	"Add anObject to the receiver. Store the object as well as the associated executor."

 	self protected: [
 		(valueDictionary associationAt: anObject ifAbsent: nil)
 			ifNil: [ valueDictionary at: anObject put: anExecutor ]
 			ifNotNil: [ :association |
 				multipleFinalizerPerObjectAction
 					cull: association
 					cull: anExecutor ] ]

WeakRegistry >> initialize: n

 	valueDictionary := WeakIdentityKeyDictionary new: n.
 	accessLock := Semaphore forMutualExclusion.
 	multipleFinalizerPerObjectAction := [ :association |
 		self error: association key printString, ' already has an executor!' ].
 	self installFinalizer.

WeakRegistry >> multipleFinalizerPerObjectAction: aBlock

 	multipleFinalizerPerObjectAction := aBlock


This way one could
- have multiple finalizers per object as it is in Squeak 4.1
- raise an error as you suggested
- replace the current executor with the new one (as it was before Squeak 4.1).

I don't know if it fits your new WeakRegistry implementation. I'm also not 
sure if this isn't a bit over-engineered.


Levente

>
>>
>> Levente
>>
>>> Okay, then why they are here? Code should have a practical use,
>>> otherwise it is just a garbage, no?
>>> Or is it an invitation to start using them?
>>> I'm not envy to everyone who will start doing it. :)
>>>
>>> I'd really like to see a good practical example where such thing could
>>> be userful,
>>> which outweights a potential problems i described before.
>>>
>>>> (but go ahead and fix it if you feel that it needs fixing)
>>>>
>>>> Cheers,
>>>>  - Andreas
>>>>
>>>>>
>>>>>> Cheers,
>>>>>>  - Andreas
>>>>>>
>>>>>> On 9/23/2010 1:23 PM, Igor Stasenko wrote:
>>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> i'd like to raise this subject once more, because i don't like it (or
>>>>>>> don't understand?).
>>>>>>>
>>>>>>> In all scenarios, where i met the need to use finalization, a single
>>>>>>> finalizer is sufficient.
>>>>>>> Moreover, there is always a single object who controls a weak
>>>>>>> reference, and it never leaks it out, to prevent
>>>>>>> the case, when some other object may obtain a strong reference on it,
>>>>>>> making it permanently held in object memory.
>>>>>>>
>>>>>>> Multiple different finalizers for single object, from design point of
>>>>>>> view, means that you having two different, not related frameworks,
>>>>>>> which using same object, and want to do something when it dies.
>>>>>>> A scenario, where its possible and userful, still don't comes into my
>>>>>>> mind.
>>>>>>> In contrary, whenever i see a use of finalizers, its in most cases
>>>>>>> about graceful control over external resource, such as:
>>>>>>> - file
>>>>>>> - socket
>>>>>>> - external memory
>>>>>>>
>>>>>>> and i really don't see how multiple finalizers per single resource
>>>>>>> could do any good.
>>>>>>>
>>>>>>> Suppose one finalizer closing a file handle, while another one
>>>>>>> flushing it buffer cache.
>>>>>>> Now, how you going to ensure, that one finalizer will execute first,
>>>>>>> before another one?
>>>>>>> And what if third framework comes into play and wants to add another
>>>>>>> finalizer on top of that, which should do something in the middle
>>>>>>> between flushing a cache and closing file handle?
>>>>>>>
>>>>>>>>  From the above, the only conclusion can be made: use a single
>>>>>>>
>>>>>>> finalizer, and put all logic&    operation ordering into it.
>>>>>>> And also, prevent leakage of object pointer (such as file handle)
>>>>>>> outside of your model, otherwise it may cause harm.
>>>>>>>
>>>>>>> That's why i think a current WeakRegistry model provoking bad design
>>>>>>> practices.
>>>>>>> I think a better behavior would be to raise an error, if something
>>>>>>> wants to register finalizer twice for a single object.
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>
>>
>>
>>
>>
>
>
>
> -- 
> Best regards,
> Igor Stasenko AKA sig.
>
>


More information about the Squeak-dev mailing list