views:

144

answers:

1

Ruby tempfile instances automatically delete their corresponding file when the references are released. However, I have one machine on which this is not the case. The code is

irb> require 'tempfile'
=> true
irb> t = Tempfile.new('test32')
=> #<File:/tmp/test32.27778.0>
irb> exit

on all of my test machines, this results in test32 getting deleted, except one. I have tried to delete a file using File.delete and unfortunately that works fine. Is there some ruby config I'm missing?

Ruby version is

ruby 1.8.6 (2009-06-08 patchlevel 369) [i686-linux].

Edit: Some additional information that has come to light in the conversation with DigitalRoss: If I explicitly release the Tempfile reference (t = nil), then the Tempfile gets cleaned up. Is is possible that the GC has been patched or altered in some way to need that?

Here's some code that works on the "good" machines but on the "bad" machine it fails

include ObjectSpace
t = "blah"
define_finalizer(t, proc {|id| print "yes finalized id=#{id}", "\n" })

On the bad machine, the "yes finalized" only prints if I explicitly set t to nil.

+2  A: 

OK, continuing the question's comment thread...

Ruby, or really, Tempfile, uses the garbage collector to manage finalizers. (I presume it works this way rather than via Kernel::at_exit in order to delete the file earlier in a long-running ruby.) Anyway, something seems different about GC on one system. Let's try to pin it down. Try this, and see if clearing the only reference to the Tempfile instance and starting GC removes the file.

ross@deb:~$ irb
>> require 'tempfile'
=> true
>> $DEBUG=true
=> true
>> t=Tempfile.new('aaa')
=> #<File:/tmp/aaa20090905-21437-1d460as-0>
>> GC.start
=> nil
>> t=nil
=> nil
>> GC.start
removing /tmp/aaa20090905-21437-1d460as-0...done
=> nil
>> exit
ross@deb:~$
DigitalRoss
Okay, perfect, thanks, I'll be checking this shortly and reporting back. In the meantime, let's leave the absurd comments on the question: in a few years who knows what will be useful :)
Yar
Very interesting: on the machine where the file is not getting cleaned out, merely setting the t = nil and doing 'exit' causes the automatic removal to happen. Exit or GC.start, but if I don't set t to nil it doesn't get cleaned up. Ideas?
Yar
also: how can I tell if my GC has been patched?
Yar
Adjusted the question to fit the new info a bit...
Yar
I checked out the ruby 1.8 source withsvn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8and found rb_gc_call_finalizer_at_exit in gc.cUnfortunately, I can't reproduce your bug, so you may need to follow along and bash on gc.c yourself a bit.
DigitalRoss
Actually, it occurs to me that trying the latest 1.8 source (which is what you get with the above checkout) might win even without any debugging. At a minimum you would have a common baseline test.
DigitalRoss
Beginning to suspect that my colleague might've applied a patch to the GC like this one http://github.com/skaes/railsbench/tree/master... later on today or tomorrow I'll know. Thanks again for all of your help. This has been a great learning experience for me, too.
Yar
Heh, scan the filesystem for ruby source :-)
DigitalRoss
Colleague says that he compiled Ruby 1.8.6 from source himself (none was available for that OS), but that aside from that there's nothing weird about it... the plot thickens.
Yar