[#46502] Twitterのサンプルでエラーなんですが。 — "T.Soejima" <clev@...2.so-net.ne.jp>
そえじま@勉強中です。
9 messages
2009/11/02
[#46517] Ruby1.8.8devでのsinatra動作について — "前川 映一" <eiichi_maekawa@...>
7 messages
2009/11/05
[#46530] ARGVの引数のデータタイプ — askar <askar75@...>
アスカルです。
9 messages
2009/11/09
[#46532] Re: ARGVの引数のデータタイプ
— Yukihiro Matsumoto <matz@...>
2009/11/09
まつもと ゆきひろです
[#46535] Re: ARGVの引数のデータタイプ
— askar <askar75@...>
2009/11/11
まつもとさん、
[#46546] CSV.openがうまく動きません — ichirojiro <ichirojiro@...>
ichiroと申します。
8 messages
2009/11/14
[#46558] 【追記】 Ruby on Railsセミナーのエントリーについて — 川井健史(CO) <takeshi.kawai@...>
Rubyistの皆様
4 messages
2009/11/15
[#46571] ruby1.9 でpostgresql8.4を利用するときについて。 — Nobuyuki Inaba <nobuyuki.inaba@...>
稲葉と申します。
8 messages
2009/11/27
[#46575] Re: ruby1.9 でpostgresql8.4を利用するときについて。
— keiichi matsunaga <ma2@...>
2009/11/30
On 11/27/2009 7:12 PM, Nobuyuki Inaba wrote:
[#46572] [ANN]12/12 DevLOVE2009Fusion を開催します — <papanda0806@...>
ruby-listのみなさん
1 message
2009/11/27
[ruby-list:46580] Re: IO#flock
From:
"NARUSE, Yui" <naruse@...>
Date:
2009-11-30 14:51:04 UTC
List:
ruby-list #46580
成瀬です。
5.5 wrote:
> IO#flock について,どうも腑に落ちない点があります。
まず、flock とはなんぞや、を理解する必要があります。
以下の「Perlの排他制御」の説明がわかりやすいと思うのですが、
flock は「ファイルをロックする仕組み」ではなく、
「ファイルをロックしているよと教えるための仕組み」なのです。
http://homepage1.nifty.com/glass/tom_neko/web/web_04.html#flock
なので、flockを使っていないプロセスには意味がありません。
> -- lock1.rb --
> open("log.txt", "a+") do |f|
> f.flock File::LOCK_EX
> f.puts 1
> sleep 5
> f.puts 2
> end
> ------
>
> -- lock2.rb --
> open("log.txt", "a+") do |f|
ここにも f.flock File::LOCK_EX が必要です。
> f.puts 3
> end
> ------
> lock1.rb を走らせた直後に lock2.rb を走らせれば,以下のように
> 動作する,と期待して実験しました。
>
> [1] まず lock1.rb が 1 を書こうとする。flush はしてないので,
> バッファーに書かれるのみ。
> [2] lock1.rb は 5 秒間のスリープに入る。
> [3] lock2.rb が 3 を書こうとするが,ロックされているので,書
> けない。待機する。
> [4] lock1.rb が 2 を書こうとする。ファイルを閉じる際に実際の
> 書き込みが行われる。
> [5] lock1.rb によるロックが解除される。
> [6] ロックが解除されたため,lock2.rb が 3 を書いてファイルを閉
> じる。
既にお気づきかも知れませんが、flock はファイルを開いた後で行われています。
つまり、a+ を使った場合、一度開いた後で、他のプロセスによって、
ファイルの末尾にデータが追加されているということになります。
この結果、現在のファイル上の位置が不定になり、実装によって差が出ます。
> その結果,log.txt には
>
> ------
> 1
> 2
> 3
> ------
>
> と書かれるはず,と思いました。
以上の通り、この期待は成り立ちません。
> 次に,lock2.rb に 1 行追加して以下のようにし,
>
> -- lock3.rb --
> open("log.txt", "a+") do |f|
> f.flock File::LOCK_EX
> f.puts 3
> end
> ------
>
> lock1.rb → lock3.rb の順に走らせました。
>
> すると,mswin187 では期待どおり 1, 2, 3 の順に書かれましたが,
> mac187 ではいつまでたっても両方のスクリプトが終了せず,
> mswin191 では 1, 2 だけが書かれて以下の例外が発生しました。
>
> lock3.rb:2:in `flock': Invalid argument - log.txt (Errno::EINVAL)
> from lock3.rb:2:in `block in <main>'
> from lock3.rb:1:in `open'
> from lock3.rb:1:in `<main>'
>
> この EINVAL の意味を
> http://msdn.microsoft.com/ja-jp/library/5814770t.aspx
> で調べたところ,
>
>> 不正な引数。関数の引数のいずれかに無効な値が指定されています。
>> たとえば、fseek 呼び出しでファイル ポインタを移動するとき、
>> 指定した元の位置がファイルの先頭より前にある場合です。
>
> と書かれていましたが,なんだかよく分かりません。
これが上述の話です。
結局の所、flock を使ってロックしながらファイルに追記する場合、
以下のようにする必要があります。
open("log.txt", IO::RDWR|IO::CREAT) do |f|
f.flock(IO::FLOCK_EX)
f.seek(0, IO::SEEK_END)
なお、ファイルが常に存在すると仮定できる場合、
IO::RDWR|IO::CREAT を "r+" と書くことができます。
つまり、こちらに関しては flock の使い方の問題です。
> 次に,PStore ではどうなのだろうと,二つのプロセスから一つの
> ファイルに PStore でデータを書こうとしたところ,mswin191 では
> やはり同じ例外が発生しました。(再現コードは略します)
で、PStore はちゃんと手当してるはずかつ、手当しているべきで、
もし普通に使っていて Errno::EINVAL が出るならばバグのように思います。
こちらの再現コードいただけませんか。
--
NARUSE, Yui <naruse@airemix.jp>