From: Tanaka Akira Date: 2011-10-31T09:30:13+09:00 Subject: [ruby-dev:44715] Re: [ruby-changes:21512] akr:r33561 (trunk): * configure.in: check dup3. 2011年10月31日5:26 KOSAKI Motohiro : > > akrさん、このコードなんですが、rb_cloexec_dup2(oldfd, newfd)のoldfdとnewfdが一致する可能性は > あるでしょうか?あるとしたら、どういう動作をすべきと意図しているAPIでしょうか? 公開APIなので、可能性はあり得るでしょう。 動作は、dup2() + CLOEXECをセット、という名前なので、 一致したら、CLOEXECをセットだけがいいかなぁ。 > といいますのも、さいきんglibcのメーリングリストでdup2とdup3とで oldfd == newfd のときの > 仕様が異なっており、libcのdup2() が システムコールのdup3() を呼ぶようにしてしまったので、 > regressionしたというバグが報告されています。 > > http://cygwin.com/ml/libc-alpha/2011-09/msg00061.html なるほど。 % svn diff --diff-cmd diff -x '-u --ignore-all-space -p' Index: io.c =================================================================== --- io.c (revision 33577) +++ io.c (working copy) @@ -239,6 +239,10 @@ rb_cloexec_dup2(int oldfd, int newfd) { int ret; + if (oldfd == newfd) { + ret = newfd; + } + else { #if defined(HAVE_DUP3) && defined(O_CLOEXEC) static int try_dup3 = 1; if (2 < newfd && try_dup3) { @@ -258,6 +262,7 @@ rb_cloexec_dup2(int oldfd, int newfd) ret = dup2(oldfd, newfd); #endif if (ret == -1) return -1; + } fd_set_cloexec(ret); return ret; } > btw, めちゃくちゃ余談なんですが、dup3でEINVALにしてるのは本当にいい仕様なんですかねえ? dup3 だけの仕様としてみれば悪くないように思えます。 oldfd == newfd かどうかで close の回数が変わってきますから、 いずれその判断はアプリケーション側でやらないといけないでしょう。 どうせやるなら dup3 の前にやることを勧めてもいいのでは。 dup2 の drop in replacement として使いにくいという点との比較については、 どの段階の状況を重視するかですかねぇ。 -- [田中 哲][たなか あきら][Tanaka Akira]