GC无法清理(原题:Tempfile不会自动删除,Ruby)

3

Ruby的tempfile实例在引用被释放时会自动删除相应的文件。然而,我有一台机器上并非如此。代码如下:

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

在我所有的测试机器上,这将导致test32被删除,除了一个。我已经尝试使用File.delete来删除文件,不幸的是它可以正常工作。我是否缺少某些Ruby配置?
Ruby版本为:
ruby 1.8.6 (2009-06-08 patchlevel 369) [i686-linux].

编辑:在与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”才会打印出来。

1
尝试这样做:>> $DEBUG=true >> 退出,并查看它是否在您的系统之间以“removing…”或其他方式不同的方式打印… - DigitalRoss
好主意,但是在好系统和坏系统上都没有任何东西。 - Dan Rosenstark
等一下,你的意思是它确实打印了“removing…”吗?如果是这样,那么下一步就是进入/usr/lib/ruby/1.8/tempfile.rb,在“print“ removing…” if $DEBUG”代码后添加一些调试代码。特别是在File.unlink之前和之后。如果$DEBUG没有打印“removing”,请在此报告。 - DigitalRoss
(或以类似方式使用调试器...) - DigitalRoss
啊哈!对不起,我现在明白了。是的,$DEBUG确实让“好”的系统打印出移除行,而坏的系统没有输出任何东西...我已经检查了tempfile.rb文件,它确实有这一行代码“print "removing ", path, "..." if $DEBUG”,就像预期的那样... - Dan Rosenstark
嗯,这有点前瞻性,但我无法格式化注释,所以我想我会打开一个答案并进行编辑,直到我们解决这个问题... :-) - DigitalRoss
2个回答

2

好的,继续问题的评论线程...

Ruby,或者说Tempfile,使用垃圾回收器来管理finalizers。(我猜它是这样工作的,而不是通过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:~$ 

好的,非常完美,谢谢。我会很快检查并回报。与此同时,让我们不要在问题上留下荒谬的评论:几年后谁知道什么会有用 :) - Dan Rosenstark
另外,我如何判断我的垃圾收集器是否已经打过补丁? - Dan Rosenstark
开始怀疑我的同事可能已经应用了像这样的GC补丁http://github.com/skaes/railsbench/tree/master...今天或明天我会知道。再次感谢您的所有帮助。对我来说,这是一次很好的学习经历。 - Dan Rosenstark
嘿,扫描文件系统以查找Ruby源代码 :-) - DigitalRoss
同事说他自己从源代码编译了Ruby 1.8.6(因为该操作系统上没有可用的版本),但除此之外,没有什么奇怪的地方...情节变得更加复杂。 - Dan Rosenstark
显示剩余3条评论

1
在1.8.7中,终结器和垃圾回收器存在问题,从描述来看,你在1.8.6中也可能遇到了同样的问题。
我们通过猴子补丁Tempfile解决了我们Rails应用程序中的问题。这个方法对你也可能有用。代码:http://github.com/jwinky/ruby_tempfile_ioerror

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接