Bug #1582
IO.new Raises Other Errors between 1.8 and 1.9
| Status: | Closed | Start date: | 06/06/2009 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | - | % Done: | 100% |
|
| Category: | - | |||
| Target version: | 1.9.2 | |||
| ruby -v: | ruby 1.9.2dev (2009-06-05 trunk 23641) [i386-darwin9.7.0] |
Description
IO.newで引数に与えたファイル記述子のファイルモードと互換性のないファイルモードを与えたとき、ruby 1.8系ではErrno::EINVALを投げるのに対し、ruby 1.9系では例外を投げず、実際に互換性のない行為を実行したときにErrno::EBADFを投げます。
io = File.open('aaa.txt', 'w')
io2 = IO.new(io.fileno, 'r') # 1.8ではこの時点でErrno::EINVAL
io.syswrite '111'
puts io2.read # 1.9ではこの時点でErrno::EBADF
私にはruby 1.8系の挙動の方が心優しい気がするのですが、どうでしょう。添付のパッチを適用すると、1.9でもIO.newの時点でErrno::EINVALを投げるようになります。
Related issues
Associated revisions
* io.c (rb_io_initialize): check if the descriptor can be accessed
in the specified open mode. [ruby-dev:38571]
History
Updated by akr (Akira Tanaka) almost 3 years ago
32bit Solaris の FILE 構造体は fd が 1byte で表現されているため、rb_fdopen で FILE構造体を生成すると、256以上の fd を扱えなくなります。
Updated by ujihisa (ujihisa .) almost 3 years ago
とするとこのパッチの参考元の、ruby1.8系のio.cのrb_io_initialize()でrb_fdopen()を呼び出している部分が気になります。
ruby_1_8_7/io.c r23641 line4366
fp->f = rb_fdopen(fd, rb_io_modenum_mode(flags));
ほかにも多数。
いっぽうruby1.9系ですとrb_io_stdio_file()で同様に
trunk/io.c r23641 line5993
fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
とrb_fdopen()が呼ばれているものの、ここではstdin, stdout, stderrしか与えられないと仮定しているためSolarisでも大丈夫、とそんな風に見えます。
手元に32bit Solarisがなくて試すことができず心もとないですが、報告までに。
Updated by akr (Akira Tanaka) almost 3 years ago
そのとおりで、1.8 では動きません。 1.9 では動くようにしたので、それを動かないようにするのは受け入れられません。
Updated by yugui (Yuki Sonoda) almost 3 years ago
- Status changed from Open to Rejected
本件はrejectということで良いでしょうか?
Updated by nobu (Nobuyoshi Nakada) almost 3 years ago
- Status changed from Rejected to Open
Updated by nobu (Nobuyoshi Nakada) almost 3 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
Applied in changeset r24102.
Updated by mame (Yusuke Endoh) about 2 years ago
- Status changed from Closed to Open
遠藤です。 なかださんの修正に regression があるみたいです。 いまから kosaki さんが詳細を書いてくれます。 -- Yusuke Endoh <mame@tsg.ne.jp>
Updated by kosaki (Motohiro KOSAKI) about 2 years ago
すいません、regressionは言い過ぎというか間違っていて修正不十分ぐらいが適当でした。
まず、Linuxでは以下の結果になります。
% ./ruby -e 'f1 = File.open("foo.txt", "w"); f1.puts "foo"; f2 = IO.new(f1.fileno); p f2.gets'
-e:1:in `gets': not opened for reading (IOError)
from -e:1:in `<main>'
% ./ruby -e 'f1 = File.open("foo.txt", "w"); f1.puts "foo"; f2 = IO.new(f1.fi
leno, "r"); p f2.gets'
-e:1:in `initialize': Invalid argument (Errno::EINVAL)
from -e:1:in `new'
from -e:1:in `<main>'
http://doc.okkez.net/static/191/class/IO.html をみると
new(fd, mode = "r") -> IO
と書いてあるので、IO.new()のmode引数のデフォルトは"r"のはずで、これは変です。
そのカラクリですが、
rb_io_initialize で
#if defined(HAVE_FCNTL) && defined(F_GETFL)
oflags = fcntl(fd, F_GETFL);
(snip)
ofmode = rb_io_oflags_fmode(oflags);
if (NIL_P(vmode)) {
fmode = ofmode;
}
というコードがあるために、引数なしの時はfd引数のアクセス権を継承する仕様に変わってしまっています。
リファレンスが正しいなら、mode引数を省略したときも単に"r"と解釈してEINVALになるべきに見えます。
これは意図的でしょうか?意図したものである場合、ドキュメントの修正をご検討くださいませ
Updated by nobu (Nobuyoshi Nakada) about 2 years ago
なかだです。 At Sat, 27 Feb 2010 01:45:54 +0900, Motohiro KOSAKI wrote in [ruby-dev:40509]: > すいません、regressionは言い過ぎというか間違っていて修正不十分ぐらいが適当でした。 > まず、Linuxでは以下の結果になります。 > > % ./ruby -e 'f1 = File.open("foo.txt", "w"); f1.puts "foo"; f2 = IO.new(f1.fileno); p f2.gets' > -e:1:in `gets': not opened for reading (IOError) > from -e:1:in `<main>' > > % ./ruby -e 'f1 = File.open("foo.txt", "w"); f1.puts "foo"; f2 = IO.new(f1.fileno, "r"); p f2.gets' > -e:1:in `initialize': Invalid argument (Errno::EINVAL) > from -e:1:in `new' > from -e:1:in `<main>' 1.8までと動作を合わせてあります。 > http://doc.okkez.net/static/191/class/IO.html をみると > > new(fd, mode = "r") -> IO 1.9のrdocではmodeのデフォルト値についての記述は削られています。 > これは意図的でしょうか?意図したものである場合、ドキュメントの修正をご検討くださいませ 1.8までのドキュメントのバグだと思います。 -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦
Updated by kosaki (Motohiro KOSAKI) about 2 years ago
2010年2月27日9:43 Nobuyoshi Nakada <nobu@ruby-lang.org>:
> なかだです。
>
> At Sat, 27 Feb 2010 01:45:54 +0900,
> Motohiro KOSAKI wrote in [ruby-dev:40509]:
>> すいません、regressionは言い過ぎというか間違っていて修正不十分ぐらいが適当でした。
>> まず、Linuxでは以下の結果になります。
>>
>> % ./ruby -e 'f1 = File.open("foo.txt", "w"); f1.puts "foo"; f2 = IO.new(f1.fileno); p f2.gets'
>> -e:1:in `gets': not opened for reading (IOError)
>> from -e:1:in `<main>'
>>
>> % ./ruby -e 'f1 = File.open("foo.txt", "w"); f1.puts "foo"; f2 = IO.new(f1.fileno, "r"); p f2.gets'
>> -e:1:in `initialize': Invalid argument (Errno::EINVAL)
>> from -e:1:in `new'
>> from -e:1:in `<main>'
>
> 1.8までと動作を合わせてあります。
>
>> http://doc.okkez.net/static/191/class/IO.html をみると
>>
>> new(fd, mode = "r") -> IO
>
> 1.9のrdocではmodeのデフォルト値についての記述は削られています。
上記URLはいちおう1.9.1用のはずなんですが、誰が修正担当なんでしょう??
あのURLを見るのが間違い? ruby-lang.org からリンクが貼ってあるから、ほとんどの人は
そこから誘導されていると思いますが
>> これは意図的でしょうか?意図したものである場合、ドキュメントの修正をご検討くださいませ
>
> 1.8までのドキュメントのバグだと思います。
動作としては現在の挙動が望ましいことには同意します。ただ、windowsのようにfcntl(GETFL)できない環境ではmode継承がされてないので挙動が変わってしまうのですがどこにも文書化されてません。これはこれで問題だと思います。
この問題の発端は [ruby-dev:40506] の (2) 課題提起でした。
とりあえず、このチケット自体は再度クローズしてよくて、[ruby-dev:40506]
で継続議論すればいいと思うのですが、私には閉じる権限がないので親切なコミッターさんが閉じてくれるのを期待します。
Updated by no6v (Nobuhiro IMAI) about 2 years ago
いまいです。 From: KOSAKI Motohiro <kosaki.motohiro_at_gmail.com> Date: Sat, 27 Feb 2010 12:07:11 +0900 >>> http://doc.okkez.net/static/191/class/IO.html をみると >>> >>> new(fd, mode = "r") -> IO >> >> 1.9のrdocではmodeのデフォルト値についての記述は削られています。 > > 上記URLはいちおう1.9.1用のはずなんですが、誰が修正担当なんでしょう?? > あのURLを見るのが間違い? ruby-lang.org からリンクが貼ってあるから、ほとんどの人は > そこから誘導されていると思いますが 私にはどう修正してよいのかまだ理解できていないのですが、リファレンスの 問題ということは認識できたので、以下に記録してしておきました。 # 題名が不適切かもしれません。 http://redmine.ruby-lang.org/issues/show/2800 >>> これは意図的でしょうか?意図したものである場合、ドキュメントの修正をご検討くださいませ >> >> 1.8までのドキュメントのバグだと思います。 > > 動作としては現在の挙動が望ましいことには同意します。ただ、windowsのようにfcntl(GETFL)できない環境ではmode継承がされてないので挙動が変わってしまうのですがどこにも文書化されてません。これはこれで問題だと思います。 引数だけでなく、記述を追加する必要もあるということですよね。 -- Nobuhiro IMAI <nov@yo.rim.or.jp> Key fingerprint = F39E D552 545D 7C64 D690 F644 5A15 746C BD8E 7106
Updated by no6v (Nobuhiro IMAI) about 2 years ago
いまいです。 From: Nobuhiro IMAI <nov_at_yo.rim.or.jp> Date: Sat, 27 Feb 2010 13:01:30 +0900 >> 上記URLはいちおう1.9.1用のはずなんですが、誰が修正担当なんでしょう?? >> あのURLを見るのが間違い? ruby-lang.org からリンクが貼ってあるから、ほとんどの人は >> そこから誘導されていると思いますが > > 私にはどう修正してよいのかまだ理解できていないのですが、リファレンスの > 問題ということは認識できたので、以下に記録してしておきました。 > # 題名が不適切かもしれません。 > > http://redmine.ruby-lang.org/issues/show/2800 > >>>> これは意図的でしょうか?意図したものである場合、ドキュメントの修正をご検討くださいませ >>> >>> 1.8までのドキュメントのバグだと思います。 >> >> 動作としては現在の挙動が望ましいことには同意します。ただ、windowsのようにfcntl(GETFL)できない環境ではmode継承がされてないので挙動が変わってしまうのですがどこにも文書化されてません。これはこれで問題だと思います。 > > 引数だけでなく、記述を追加する必要もあるということですよね。 今のところ、メソッドシグネチャで引数にデフォルト値がある場合は書いてお く、というルール[1]があるようなので、説明文だけ追加[2]しました。内容が あっているか見ていただけるとありがたいです。 1. http://www.fdiary.net/ml/ruby-reference-manual/msg/360 2. http://redmine.ruby-lang.org/repositories/diff/rurema?rev=3924 -- Nobuhiro IMAI <nov@yo.rim.or.jp> Key fingerprint = F39E D552 545D 7C64 D690 F644 5A15 746C BD8E 7106
Updated by no6v (Nobuhiro IMAI) about 2 years ago
いまいです。 From: KOSAKI Motohiro <kosaki.motohiro_at_jp.fujitsu.com> Date: Wed, 3 Mar 2010 13:23:29 +0900 >> 今のところ、メソッドシグネチャで引数にデフォルト値がある場合は書いてお >> く、というルール[1]があるようなので、説明文だけ追加[2]しました。内容が >> あっているか見ていただけるとありがたいです。 >> >> 1. http://www.fdiary.net/ml/ruby-reference-manual/msg/360 >> 2. http://redmine.ruby-lang.org/repositories/diff/rurema?rev=3924 > > 確認しました。 ありがとうございます。 > エンドユーザは自分の環境がfcntlが利用できる環境かどうか知っているのだろうか? > と素朴な疑問がわきました。 require "fcntl" できるとか、今回の用途では Fcntl::F_GETFL が定義されて いる、とか見ればいいのかな?私自身、よく分かってません。 > まったく分かってなくて恐縮なのですが、リファレンスの習慣的には「xxが利用できる環境」 > という表記と「Windows環境では」という表記のどちらが一般的なのでしょうか。 > 前者の場合、なにも問題ないと思います。 行単位でしか調べていませんが、「Windows 環境」という表現は少なく、例え ば、Encoding.locale_charmap の説明には「nl_langinfo 等がない環境では」 という表現があったので、今回はとりあえずこのままにしておこうと思います。 -- Nobuhiro IMAI <nov@yo.rim.or.jp> Key fingerprint = F39E D552 545D 7C64 D690 F644 5A15 746C BD8E 7106
Updated by wanabe (_ wanabe) about 2 years ago
- Status changed from Open to Closed
r24102 についての議論は [Bug #2796] で、とのことですのでクローズさせて頂きます。 問題がありましたら再オープンをお願いします。