2009-09-03 3 views
2

У меня есть эта команда в контроллере Railsи Временный файл Garbage Collection

open(source) { |s| content = s.read } 
    rss = RSS::Parser.parse(content, false) 

и это приводит к временным файлам, которые Наполнение (дефицитное) дисковое пространства.

Я исследовал эту проблему в какой-то степени, и оказывается, что где-то в стеке это происходит:

io = Tempfile.new('open-uri') 

, но это выглядит, как этот экземпляр TempFile никогда не получает явно закрыт. У него есть

def _close # :nodoc: 

метод, который может срабатывать автоматически при сборке мусора?

Любая помощь в понимании того, что происходит или как очистить tempfiles, будет действительно полезной.

ответ

1

похоже, что _close закрывает файл, а затем ждет сбора мусора, чтобы отсоединить (удалить) файл. Теоретически вы можете принудительно отключить сразу, вызвав метод Tempfileclose! вместо close или позвонить по номеру close(true) (который вызывает внутри страны close!).

редактировать: Но проблема в открытой Ури, который из рук - и это не дает никаких обещаний по очистке после себя: он просто предполагает, что сборщик мусора завершит все Tempfile с в свое время ,

В таком случае у вас нет выбора, кроме как позвонить самому сборщику мусора, используя ObjectSpace.garbage_collect (see here). Это должно привести к удалению всех временных файлов.

+0

так, кто называет _Закрыть? Я не думаю, что без перехвата обезьян я не имею доступа к этому временному файлу. –

+0

Я вижу проблему сейчас. Я добавил дополнительную информацию в ответ, надеюсь, это сработает для вас. – Guss

+0

Спасибо за это! Я не могу себе представить, что вызов GC явно решит проблему. В моем тестировании единственный способ получить tempfile для НЕ очистки - это прервать программу. Поэтому я не могу понять, что может произойти. –

1

Определенно не ошибка, а неисправная ошибка ввода IO. Buffer.io является либо StringIO, если значение @size меньше 10240 байт или Tempfile, если над этой суммой. Условие обеспечения в OpenURI.open_uri() вызывает метод close(), но поскольку это может быть объект StringIO, который не имеет метода close!(), Он просто не может просто вызвать close!().

Исправления, я думаю, будет либо один из них:

обеспечить Пункт проверку для класса и вызывает либо StringIO.close или Tempfile.close! по мере необходимости.

--или--

Класс Buffer нуждается в финализации, который обрабатывает проверку класса и вызывает правильный метод.

Предоставлено ни одним из них не исправлено, если вы не используете блок для обработки ввода-вывода, но я предполагаю, что в этом случае вы можете выполнить свою собственную проверку, поскольку open() возвращает объект IO, а не буфер объект.

Lib - большой кусок грязного кода, imho, поэтому он может использовать работу для очистки. Думаю, я могу это сделать, просто для удовольствия. ^.^

+0

SynTruth, я получаю эту идею, но на языке утиного ввода вы не проверьте класс. Вы проверяете, отвечает ли он методу :). Во всяком случае, я так далеко от этой проблемы, что я не знаю, исправили ли вы это. Но сообщите об этом, если хотите, просто ради любопытства. –

4

Если вы действительно хотите, чтобы заставить open-uri не использовать временный файл, вы можете связываться с OpenURI::Buffer::StringMax константой:

> require 'open-uri' 
=> true 
> OpenURI::Buffer::StringMax 
=> 10240 
> open("http://www.yahoo.com") 
=> #<File:/tmp/open-uri20110111-16395-8vco29-0> 
> OpenURI::Buffer::StringMax = 1_000_000_000_000 
(irb):10: warning: already initialized constant StringMax 
=> 1000000000000 
> open("http://www.yahoo.com") 
=> #<StringIO:0x6f5b1c> 

Это потому, что в этом фрагменте из open-uri.rb:

class Buffer 
    [...] 
    StringMax = 10240 
    def <<(str) 
    [...] 
    if [...] StringMax < @size 
     require 'tempfile'