top | item 42570697

(no title)

ryanmjacobs | 1 year ago

I'm pleasantly surprised to see this improvement:

  Tempfile.create(anonymous: true) removes the created temporary file
  immediately. So applications don’t need to remove the file.
  [Feature #20497]
I use a similar pattern a lot:

  file = Tempfile.new.tap(&:unlink)
  file << "... some really large data to pipe"
  system("md5sum", in: file.tap(&:rewind))
It's a neat trick to leverage the filesystem for large amounts of data (e.g. "psql \copy" generation), without littering tempfiles everywhere. Once the last fd disappears, the filesystem releases the data; so you don't have to "trap" signals and add cleanup routines. (Hint: you can also use these unlinked-tempfiles for command output, e.g. huge grep output, etc.)

On Linux systems, `open(..., O_TMPFILE)` is typically used, which provides additional safety. The created file is initially unnamed (no race condition between `open` and `unlink`).

When I needed safety, my non-portable solution was to use Ruby's syscall feature. (Btw, I love that you can do this.)

  require "fcntl"

  SYS_OPEN   = 2
  O_TMPFILE  = 0x00410000
  O_RDWR     = Fcntl::O_RDWR

  def tmpfile
    mode = O_RDWR | O_TMPFILE
    fd = syscall(SYS_OPEN, "/dev/shm", mode, 0644)
    IO.for_fd(fd)
  end
But... Another pleasant surprise from the PR (https://bugs.ruby-lang.org/issues/20497).

  Linux 3.11 has O_TMPFILE to create an unnamed file.
  The current implementation uses it.
Excellent to see :) Makes the PR even better!

discuss

order

15155|1 year ago

This is available in older Ruby versions by using the upstream `tempfile` gem version.