B
Brian Candler
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
}
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.
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
}
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.