Ruby Tempfile and Garbage Collection
Sun, Jan 31, 2016Tempfile gives you an easy way to quickly create a temporary file without having to worry about generating a file name that doesn’t already exist and cleaning up the file after you are done. However, you have to be aware that the temporary file will be deleted when the tempfile instance is garbage collected.
From ruby Tempfile documentation
When a Tempfile object is garbage collected, or when the Ruby interpreter exits, its associated temporary file is automatically deleted.
Here is an example that will cause intermittent problem
# create tempfile and return the path
def create_tempfile(body)
tmpfile = Tempfile.new
tmpfile.write(body)
tmpfile.close # so it will actually write the content to disk
tmpfile.path
end
path = create_tempfile(‘hello’)
File.read(path)
In some cases you would get an error that the file does not exist. Because what gets returned from the create_tempfile method is the tempfile path, so tempfile is no longer referenced anywhere once create_tempfile
is done. When garbage collector runs, it will cleanup tmpfile and also delete the file.
You can test this by manually starting the garbage collector, and always get an error when trying to read the file.
path = create_tempfile(‘hello’)
GC.start
File.read(path)
In order to avoid this issue, you need to return the tmpfile instance. So as long as your code still references the tempfile instance, it will not be garbage collected.
def create_tempfile(body)
tmpfile = Tempfile.new
tmpfile.write(body)
tmpfile.close
tmpfile
end
file = create_tempfile(‘hello’)
GC.start
File.read(file.path) # this will work even after garbage collection ran