[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Finalizers...

Michael Neumann

11/10/2004 12:23:00 PM

Hi,

Are finalizers (ObjectSpace.define_finalizer) executed atomicly? Or can
they be interrupt by other finalizers (or threads)?

I've noticed that finalizers can't raise exceptions. They silently
abort. That's a feature, but hard to find bugs in finalizers ;-)

Regards,

Michael


5 Answers

Carlos

11/15/2004 12:36:00 AM

0

[Michael Neumann <mneumann@ntecs.de>, 2004-11-10 13.23 CET]
> Hi,
>
> Are finalizers (ObjectSpace.define_finalizer) executed atomicly? Or can
> they be interrupt by other finalizers (or threads)?

There are run with Thread.critical=true.

------------------------------------------------------ Thread::critical=
Thread.critical= boolean => true or false
------------------------------------------------------------------------
Sets the status of the global ``thread critical'' condition and
returns it. When set to +true+, prohibits scheduling of any
existing thread. Does not block new threads from being created and
run. Certain thread operations (such as stopping or killing a
thread, sleeping in the current thread, and raising an exception)
may cause a thread to be scheduled even when in a critical section.
+Thread::critical+ is not intended for daily use: it is primarily
there to support folks writing threading libraries.

Hope this helps.


Paul Brannan

11/15/2004 3:02:00 PM

0

On Wed, Nov 10, 2004 at 09:23:04PM +0900, Michael Neumann wrote:
> Are finalizers (ObjectSpace.define_finalizer) executed atomicly? Or can
> they be interrupt by other finalizers (or threads)?

I believe finalizers are only called from the garbage collector, and the
garbage collector doesn't do anything if called re-entrantly.

Also, as Carlos pointed out, finalizers are run with
Thread#critical=true, so they won't be interrupted by another thread nor
will they be interrupted by a timeout.

I think that covers all the cases, except if you explicitly call the
finalizer proc yourself.

Paul



Michael Neumann

11/15/2004 3:22:00 PM

0

Paul Brannan wrote:
> On Wed, Nov 10, 2004 at 09:23:04PM +0900, Michael Neumann wrote:
>
>>Are finalizers (ObjectSpace.define_finalizer) executed atomicly? Or can
>>they be interrupt by other finalizers (or threads)?
>
>
> I believe finalizers are only called from the garbage collector, and the
> garbage collector doesn't do anything if called re-entrantly.

hm, if you allocate objects inside the finalizer, the garbage collector
could be invoked while we're *in* the finalizer.

def run
p2 = proc { puts "fin" }

obj = Object.new
ObjectSpace.define_finalizer(obj, proc {
puts "enter obj"
loop do
x = Array.new
ObjectSpace.define_finalizer(x, p2)
end
puts "leave obj"
})
end

run

outputs:

enter obj
fin
fin
.
.
.

This usually will not happen using "real" finalizers, but maybe in some
rare cases... who knows.

So, do I really have to invoke "GC.disable" at the top of my finalizer,
to be 100% sure, that no other finalizers are invoked while I'm in the
finalizer?

Regards,

Michael


Paul Brannan

11/15/2004 3:32:00 PM

0

On Tue, Nov 16, 2004 at 12:21:33AM +0900, Michael Neumann wrote:
> hm, if you allocate objects inside the finalizer, the garbage collector
> could be invoked while we're *in* the finalizer.

Oh, my bad. The during_gc flag is cleared before the finalizers are
invoked.

Paul



Mark Hubbart

11/15/2004 6:29:00 PM

0

Hi,

On Wed, 10 Nov 2004 21:23:04 +0900, Michael Neumann <mneumann@ntecs.de> wrote:
> Hi,
>
> Are finalizers (ObjectSpace.define_finalizer) executed atomicly? Or can
> they be interrupt by other finalizers (or threads)?
>
> I've noticed that finalizers can't raise exceptions. They silently
> abort. That's a feature, but hard to find bugs in finalizers ;-)

% ruby <<EOP
f = lambda do
begin
0/0
rescue ZeroDivisionError => e
puts e, e.backtrace
end
end
ObjectSpace.define_finalizer "foo", f
EOP
divided by 0
-:3:in `/'
-:3
-:1:in `call'
-:8

One could imagine an ObjectSpace.define_debug_finalizer:

### untested ###
def ObjectSpace.define_debug_finalizer(obj, callable, io = STDERR)
wrapper = lambda do |id|
begin
callable.call(id)
rescue Exception=>e
io.puts e, e.backtrace
end
end
ObjectSpace.define_finalizer obj, wrapper
end

cheers,
Mark