Project

General

Profile

Actions

Feature #11715

closed

Tempfile.create unlinked file silently fails

Added by ksss (Yuki Kurihara) about 9 years ago. Updated about 9 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
[ruby-dev:49370]

Description

ファイルを作成してデータを書き込んでから読み込んで利用するプログラムにおいて、
全て書き込み終わるまでは他のプロセスからアクセスされたくないので、
ファイルをアトミックに作成する方法として、Tempfileに一旦書き込んでからrenameする方法が使われています。

https://github.com/rails/rails/blob/7e62a65e18d1e97debfa1c6215b7541157489115/activesupport/lib/active_support/core_ext/file/atomic.rb#L19-L51

似たようなことをしたい場合、
Tempfile.openでは、以下の場合エラーが発生しませんが、

Tempfile.open("foo") do |f|
  f.close
  File.rename f.path, "bar"
end

Tempfile.createの場合はエラーになります。

Tempfile.create("foo") do |f|
  f.close
  File.rename f.path, "bar"
end
#=> Errno::ENOENT: No such file or directory

Tempfile.createでもエラーが発生しないようになると、
ライブラリーなどの挙動を変えずに、より両者で似たような挙動を期待できるようになるのではないでしょうか。
それとも意図された挙動なのでしょうか。

エラーが発生しないように修正したパッチを添付します。


Files

tempfile.patch (947 Bytes) tempfile.patch ksss (Yuki Kurihara), 11/19/2015 02:12 PM

Updated by akr (Akira Tanaka) about 9 years ago

  • Status changed from Open to Rejected

/tmp のような複数のユーザが共有するディレクトリでは不確実な操作
(たとえば存在しないかもしれないファイルの削除) はしないほうがいいと思います。

ライブラリ側でファイルを消すのがエラーになって困るというのであれば、
ブロックを使わない形で Tempfile.create を呼び出してください。
そうすればファイルは消されないので、rename するなり消すなり、アプリケーション側で自由に行えます。

Updated by ksss (Yuki Kurihara) about 9 years ago

納得しました。ありがとうございました。

Updated by naruse (Yui NARUSE) about 9 years ago

余談ですが、

そういう用途だったらopenに最近O_TMPFILEってフラグが追加されているので、最初は名前無しファイルで作って、
終わったらlinkat(2)で永続化するっていうのを提供してもよいかもしれませんねぇ。
http://linuxjm.osdn.jp/html/LDP_man-pages/man2/open.2.html

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0