[ruby-talk:87730] race condition in makedirs
makepath では複数のディレクトリを親から順番に作っていく。 このとき、ディレクトリかどうかチェックしてから mkdir(2) すると別プロセスがすでに作っている場合があるからまずい、 という指摘があった。 名指しされたのは ftools だけど、 fileutils も全く同じ問題がある。
そこで、そこらへんに転がっていた mkinstalldirs と GNU mkdir のソースコードを見て挙動を確認した。 それによると、まず mkdir してみて、 失敗したときにそれがディレクトリかどうかチェックしているようだ。
よって、fileutils もこの方式でいくことにした。
で、soap/netHttpClient.rb を見てみた。
とりあえずソースコードだけ見ると、 netHttpClient.rb の warning は例の HTTP#get の返り値変更のやつだな。 これは 1.8 限定なら簡単になおせる。 しかしテストせずにいじるのは恐いので、 まず SOAP 環境を作らないとな。
他に出てるのは net/https か。 これはいきなりメソッドを上書きしているのがよくないので、 remove_method してから定義すれば直るな。 ていうか net/https は net/http にマージしちゃってもいいんじゃなかろうか? しかしテストせずにいじるのは恐いので、 まず https な環境を作らないとな。
とか言ってるあいだに深みにはまっていくのが定番パターンである。
http://distcc.samba.org/ ( ただの日記 経由)
分散コンパイルしてくれるらしい。これはいいねえ。 最近のコンパイルでは I/O より CPU パワーが命だからな。
Cygwin でテスト走らせたらなぜかカレントディレクトリが真っ新に! ひいー。
というのは置いといて (直したけど)。
mswin32 版でテスト走らせたらエラーが!
というのも置いといて (直したけど)。
NetBSD/Alpha で失敗した。 なぜか FileUtils.mkdir_p('tmpdir/d/') と最後にスラッシュを付けてると失敗する。 mswin32 はともかく NetBSD で失敗するのはおかしーよ! おかしーですよ! ありえねーよ!
aamine@asv800 % uname -srm NetBSD 1.6.1 alpha aamine@asv800 % ls dir /usr/local/bin/gnuls: dir: No such file or directory aamine@asv800 % ruby -e 'Dir.mkdir("dir/")' -e:1:in `mkdir': No such file or directory - dir/ (Errno::ENOENT) from -e:1 aamine@asv800 % ruby -e 'Dir.mkdir("./dir/")' -e:1:in `mkdir': No such file or directory - ./dir/ (Errno::ENOENT) from -e:1 aamine@asv800 % ruby -e 'Dir.mkdir("dir")' aamine@asv800 %
ええー。まじで?
いやいや、これはきっと ruby が原因なんだな。 ありがちな罠だ。
aamine@asv800 % cat mkdir.c #include <stdio.h> #include <sys/stat.h> int main(int argc, char **argv) { if (mkdir("dir", 0777)) { perror("dir/"); exit(1); } exit(0); } aamine@asv800 % gcc -Wall -omkdir mkdir.c aamine@asv800 % ./mkdir dir/: No such file or directory aamine@asv800 % ls dir /usr/local/bin/gnuls: dir: No such file or directory
世の中は無情にも非情だった。
しかたないので末尾のスラッシュはあらかじめ sub しておくことにしよう。 これで Linux NetBSD Cygwin VC++6 で通りました。
http://diary.does.notwork.org/gotoyuzo/?date=20031211#p01 (AD-HOCKERY DIARY)
むー、パス末尾のスラッシュは渡す側が取り除くのが正しいんですか。 さらに調査すると、coreutils-5.0/lib/mkdir.c にも スラッシュを取る関数があって、そのコメントに
/* This function is required at least for NetBSD 1.5.2. */
とありました。
ところで、今の今までずっと ad-hocky diary だと思ってましたよ。
あ、NetBSD だとディレクトリを cat できるんだな。 Linux はできないんだよなー。 便利って言えば便利だけど、なんとなく納得いかないものがある。
ディレクトリを open できると grep '^ufs_mkdir' ufs/* ってしたときにディレクトリが混ざってても エラーにならないのがちょっと便利。
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
ディレクトリが cat できるのは、UNIX的には伝統です。
昔(4.2BSDでffsが導入されるよりも前)はgetdent(2)とか
readdir(3)なんてものはなくて、アプリケーションが
read(2)でディレクトリを直接読んでました。
もっとも、NFSを介すと、どんなUNIXでもread(2)できなく
なります。
ディレクトリ名の末尾に"/"をつけても良いかどうかは、
POSIX的にはどちらが正しいんだか良くわからない状況
じゃないかと思います。移植性を重視するなら、つけない
方が安全でしょう。(netbsd @ re.soum メーリングリスト
でも最近議論されてます。)
あ、昔ディレクトリが読めたってのは知ってるんです。
Solaris とかいじってましたし、昔話が好きなもんで。
大昔は vi で編集したこともあったらしいですね。
と思ったら、そうか、全く逆の意図に読めるんですね……。
「便利だけど納得がいかない」のは、Linux でディレクトリを
read できないことについて書いているわけです。
わかりにくかったですね。すみません。