From: Sean O'Halpin Date: 2008-09-18T00:24:41+09:00 Subject: Re: Threads preventing garbage collection? On Wed, Sep 17, 2008 at 10:07 AM, Brian Candler wrote: > I wondered if someone can explain the following behaviour to me. > > For some reason, in the following code the instances of object Foo are > prevented from being garbage collected. > > def make_thread > Thread.new { sleep 2 } > end > > class Foo > attr_accessor :bar > end > > 10.times { |i| > f = Foo.new > f.bar = make_thread > } > > GC.start > sleep 1 > GC.start > > ObjectSpace.each_object(Foo) { |o| p o } > > But if I modify the code as follows, then the Foo objects are > garbage-collected just fine: > > --- tst.rb 2008-09-17 10:00:27.000000000 +0100 > +++ tst2.rb 2008-09-17 10:03:04.000000000 +0100 > @@ -6,9 +6,10 @@ > attr_accessor :bar > end > > + threads = (0..9).collect { make_thread } > 10.times { |i| > f = Foo.new > - f.bar = make_thread > + f.bar = threads[i] > } > > GC.start > > It's as if the thread created by Thread.new keeps a reference to the Foo > object which existed at the time, even though inside make_thread it is > out of scope, so it shouldn't even know about it. > > By tweaking the 'sleep' values, it also seems that when the thread > terminates it then does permit the Foo instance to be garbage-collected. > > Any ideas as to what's going on? I get the same results on these two > versions of Ruby: > > ruby 1.8.4 (2005-12-24) [i486-linux] > ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-linux] > > Thanks, > > Brian. > -- The threads are not garbage collected until they terminate and so the Foo instances are not being GC'd. You're not sleeping long enough at the end of your script. Try using something like: GC.start sleep 20 GC.start and see how many instances are still hanging around at the end of your script. Regards, Sean