Ruby Tempfile and Garbage Collection

Tempfile 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