GC未清理(was:Tempfile未自动删除,Ruby)

GC未清理(was:Tempfile未自动删除,Ruby),ruby,configuration,Ruby,Configuration,Ruby tempfile实例在释放引用时自动删除其相应的文件。然而,我有一台机器,但情况并非如此。代码是 irb> require 'tempfile' => true irb> t = Tempfile.new('test32') => #<File:/tmp/test32.27778.0> irb> exit 编辑:在与DigitalRoss的对话中了解到的一些附加信息:如果我明确释放Tempfile引用(t=nil),那么Tempfile将被清

Ruby tempfile实例在释放引用时自动删除其相应的文件。然而,我有一台机器,但情况并非如此。代码是

irb> require 'tempfile'
=> true
irb> t = Tempfile.new('test32')
=> #<File:/tmp/test32.27778.0>
irb> exit
编辑:在与DigitalRoss的对话中了解到的一些附加信息:如果我明确释放Tempfile引用(t=nil),那么Tempfile将被清理GC是否可能以某种方式进行了修补或更改以满足需要?

这里有一些代码在“好”机器上运行,但在“坏”机器上失败

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

在坏机器上,只有当我显式地将t设置为nil时,“yes finalized”才会打印。

好,继续问题的注释线程

Ruby,或者确切地说,
Tempfile
,使用垃圾收集器来管理终结器。(我假设它是这样工作的,而不是通过Kernel::at_exit在长时间运行的ruby中删除文件。)总之,一个系统上的GC似乎有所不同。让我们试着把它固定下来。试试这个,看看清除对Tempfile实例的唯一引用并启动GC是否会删除该文件

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:~$ 
ross@deb:~$irb
>>需要“临时文件”
=>正确
>>$DEBUG=true
=>正确
>>t=Tempfile.new('aaa')
=> #
>>GC.start
=>零
>>t=零
=>零
>>GC.start
拆卸/tmp/aaa20090905-21437-1d460as-0…完成
=>零
>>出口
ross@deb:~$ 

在1.8.7中,终结器和垃圾收集器存在问题,从描述中可以看出,您在1.8.6中遇到了相同的问题


我们在rails应用程序中通过修补Tempfile解决了这个问题。也许对你也有用。代码:

尝试此操作:>>$DEBUG=true>>退出,然后查看它是否打印“删除…”或以其他方式在您的系统之间执行不同的操作…好主意,但无论是好的系统还是坏的系统都没有。等一下,您的意思是它确实打印“删除…”?如果是这样,那么下一步就是转到/usr/lib/ruby/1.8/tempfile.rb,在“print”之后添加一些调试代码,删除“If$DEBUG”代码。尤其是在File.unlink前后。如果$DEBUG没有打印“删除”,请在这里报告。(或者以类似方式使用调试器…)啊哈!对不起,我现在明白了。是的,$DEBUG会使“好”系统打印删除行,而坏系统不会输出任何内容。。。我已经检查了tempfile.rb,它确实有这一行“print”removing,path,“…”if$DEBUG“,正如预期的那样…好的,很好,谢谢,我将很快检查并报告。同时,让我们对这个问题留下荒谬的评论:几年后谁知道什么会有用:)非常有趣:在没有清除文件的机器上,仅仅设置t=nil并执行“exit”操作就会导致自动删除。Exit或GC.start,但如果我没有将t设置为nil,它不会被清除。想法?还有:我怎样才能知道我的GC是否已经被修补?我与svn co一起检查了ruby 1.8源代码,并在GC.c的_出口处找到了rb_GC_call_finalizer_。不幸的是,我无法复制你的bug,所以你可能需要跟随并自己对GC.c进行一点抨击。事实上,我突然想到尝试最新的1.8源代码(这是您通过上述签出获得的结果)即使不进行任何调试也可能获胜。至少您将有一个通用的基线测试。
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:~$