From: Charles Oliver Nutter Date: 2008-08-01T17:47:43+09:00 Subject: [ruby-core:18049] Re: finalizers in 1.8 no longer run after gc_sweep() In most garbage collectors I know of, it's unwise to have hard expectations about when finalizers are going to be run. Not only does it impose considerably more overhead on the underlying GC (since it can't do finalizers as a separate step from sweeping), but it is impossible to implement on black-boxed GC implementations that don't make the same guarantee. Obviously it's a problem if this really isn't finalizing until the process terminates or GC.start is called, but there should be no expectation that finalizers will run immediately after any GC calls...the GC should be free to call finalizers when it's appropriate to do so. I'm not saying this might not be a bug...just that finalization shouldn't be expected to run immediately after an object is collected. - Charlie Eric Hodel wrote: > This was brought up by Roger Pack in [ruby-talk:309757]. > > In 1.6, a finalizer would run immediately after the garbage collector > collected an object. Now they are no longer run until the process > terminates or an explicit GC.start is run: > > $ cat final.rb > $finalizer_proc = proc do |obj_id| puts "#{obj_id} finalized" end > > def a() b end > def b() c end > def c() d end > def d() e end > def e() f end > def f() g end > def g() h end > def h() i end > def i() j end > def j() k end > def k() make_obj end > > def make_obj > o = Object.new > ObjectSpace.define_finalizer o, $finalizer_proc > o.__id__ > end > > obj_id = a > > puts "#{obj_id} created" > > a = [] > s = 'a' > > begin > loop do > ObjectSpace._id2ref obj_id > a << s.succ! > print "#{s}\r" > end > rescue RangeError > puts > puts "#{obj_id} collected" > end > > $ ruby -v final.rb > ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0] > 81660 created > avr > 81660 collected > 81660 finalized > $ ruby16 -v final.rb > ruby 1.6.8 (2005-09-21) [i386-darwin9.4.0] > 1117686 created > 1117686 finalized > omu > 1117686 collected > $ > > I would expect the finalized line to print before the collected line at > all times. This is no longer true. > > Running the finalizers in gc_sweep() was removed in r7090. The > following patch restores the 1.6 behavior, but I'm unsure if it > re-introduce some problem from [ruby-dev:24536]. > > Index: gc.c > =================================================================== > --- gc.c (revision 18230) > +++ gc.c (working copy) > @@ -1196,7 +1196,7 @@ gc_sweep() > > /* clear finalization list */ > if (final_list) { > - deferred_final_list = final_list; > + finalize_list(final_list); > return; > } > free_unused_heaps(); > >