From: Eric Mahurin Date: 2005-06-20T07:55:00+09:00 Subject: Re: GC.disable not working? --- Robert Klemme wrote: > "Robert Klemme" schrieb im Newsbeitrag > def self.list > FOOS.each do |oid, x| > begin > p ObjectSpace._id2ref(oid) > rescue RangeError => e > puts "#{oid} collected but not finalized: > x=#{x.inspect}" > end > end > end I assume you meant FOOS above. I fixed it. Just catching a RangeError is not all you need. You better make sure the object is finalized and the finalizer removes its oid from FOOS before the space is reclaimed. Otherwise oid could refer to a completely new object and you wouldn't detect it. On top of that, these finalizers can't be called while this FOOS.each loop is going on. Otherwise you'd get an error about the hash being modified while your iterating over it. It is like the GC and finalizers are in another thread, but unfortunately you can't control it like a thread (i.e. Thread.critical=). This is my primary dilemma. These issues may be very difficult to detect problems with and you may need 1000's of tests to excite the GC differently to detect the problem. You must be prepared for this using _id2ref. > > This approach works ok - you'll have to imagine that x > contains > > information needed for proper cleanup of a Foo instance, > for example, an > > open IO instance (although I'm sure that will do proper > cleanup on > > finalization): > > > > class Foo > > FOOS = {} > > > > def initialize(x) > > self.x=x > > > > ObjectSpace.define_finalizer(self) do |oid| > > puts "Cleanup of #{oid} with #{FOOS[oid]}" > > end > > end Won't work. This is the exact mistake I made when first trying to use a finalizer. In the above, you gave define_finalizer a Proc that has a Binding with direct access to self (a Foo). This creates an unintended reference to the object in ObjectSpace/GC. It will never be GCed because of this. It took me a while to figure this out. The Proc/Method needs to be defined in a context that doesn't have access to the object you are trying to put a finalizer on. For this reason, I don't think define_finalizer should even allow the block form. Also, a Proc#unbind would be nice to have in this situation. Also, I assume you'd want to delete the oid entry from FOOS in this finalizer, right? > > def x=(y) > > @x = y > > FOOS[object_id] = y > > end > > > > def x() @x end > > end ____________________________________________________ Yahoo! Sports Rekindle the Rivalries. Sign up for Fantasy Football http://football.fantasysports.yahoo.com