def atomic_create_and_write_file(filename, perms = 0666)
      require 'tempfile'
      tmpfile = Tempfile.new(File.basename(filename), File.dirname(filename))
      tmpfile.binmode if tmpfile.respond_to?(:binmode)
      result = yield tmpfile
      tmpfile.close
      ATOMIC_WRITE_MUTEX.synchronize do
        begin
          File.chmod(perms & ~File.umask, tmpfile.path)
        rescue Errno::EPERM
          # If we don't have permissions to chmod the file, don't let that crash
          # the compilation. See issue 1215.
        end
        File.rename tmpfile.path, filename
      end
      result
    ensure
      # close and remove the tempfile if it still exists,
      # presumably due to an error during write
      tmpfile.close if tmpfile
      tmpfile.unlink if tmpfile
    end
def atomic_create_and_write_file(filename, perms = 0666)
      require 'tempfile'
      tmpfile = Tempfile.new(File.basename(filename), File.dirname(filename))
      tmpfile.binmode if tmpfile.respond_to?(:binmode)
      result = yield tmpfile
      tmpfile.close
      ATOMIC_WRITE_MUTEX.synchronize do
        begin
          File.chmod(perms & ~File.umask, tmpfile.path)
        rescue Errno::EPERM
          # If we don't have permissions to chmod the file, don't let that crash
          # the compilation. See issue 1215.
        end
        File.rename tmpfile.path, filename
      end
      result
    ensure
      # close and remove the tempfile if it still exists,
      # presumably due to an error during write
      tmpfile.close if tmpfile
      tmpfile.unlink if tmpfile
    end
This creates a temp file and yields it for writing. When the
 write is complete, the file is moved into the desired location.
 The atomicity of this operation is provided by the filesystem's
 rename operation.

 @param filename [String] The file to write to.
 @param perms [Integer] The permissions used for creating this file.
   Will be masked by the process umask. Defaults to readable/writeable
   by all users however the umask usually changes this to only be writable
   by the process's user.
 @yieldparam tmpfile [Tempfile] The temp file that can be written to.
 @return The value returned by the block.