Bug #2747

io.dup doesn't handle pos properly

Added by Motohiro KOSAKI about 4 years ago. Updated over 1 year ago.

[ruby-dev:40424]
Status:Rejected
Priority:Normal
Assignee:-
Category:core
Target version:2.0.0
ruby -v:ruby 1.9.2dev (2010-02-03) [x86_64-linux] Backport:

Description

=begin
記録のために、IRCから転記します。

duptest.rb


f1 = File.new("foo.txt")
f2 = f1.dup()
p f1.pos
p f2.gets
p f1.pos
p f2.pos

foo.txt


1
2
3

このようなテストプログラムを実行すると、

0
"1\n"
6
2

となります。dupはf1とf2で同じposが返るべきであるし、6はどこから出てきたのかよく分かりません。
=end


Related issues

Related to ruby-trunk - Bug #2516: IO#reopen Compatibility (original: [ruby-dev:39479]) Rejected 12/23/2009

History

#1 Updated by Motohiro KOSAKI about 4 years ago

=begin
#2516 と関連しています
=end

#2 Updated by Motohiro KOSAKI about 4 years ago

=begin
1.8.6での挙動

% /usr/bin/ruby -v duptest.rb
ruby 1.8.6 (2009-08-04 patchlevel 383) [x86_64-linux]
0
"1\n"
0
2

f1とf2のposがずれているので、これもおかしい

=end

#3 Updated by Motohiro KOSAKI about 4 years ago

=begin
6の秘密はstraceが教えてくれている

dup(4) = 5
lseek(4, 0, SEEKCUR) = 0
lseek(5, 0, SEEK
SET) = 0
lseek(4, 0, SEEKCUR) = 0
write(1, "0\n", 20
) = 2
read(5, "1\n2\n3\n", 8192) = 6
write(1, "\"1\n\"\n", 6"1\n"
) = 6
lseek(4, 0, SEEK
CUR) = 6
write(1, "6\n", 26
) = 2
lseek(5, -4, SEEKCUR) = 2
lseek(5, 0, SEEK
CUR) = 2
write(1, "2\n", 22
)

read(f2, buf, 8192)でバッファリング読み込みしたあと、オフセットを戻すのを忘れて
lseek(f1, 0, SEEK_CUR) でposを読み込むのでファイル終端のposが得られている。

=end

#4 Updated by Yusuke Endoh about 4 years ago

=begin
kosaki さん
遠藤です。

2010年2月15日21:40 Motohiro KOSAKI redmine@ruby-lang.org:

6の秘密はstraceが教えてくれている

snip

read(f2, buf, 8192)でバッファリング読み込みしたあと、オフセットを戻すのを忘れて
lseek(f1, 0, SEEK_CUR) でposを読み込むのでファイル終端のposが得られている。

dup の前後でバッファを共有していないのが問題ですよね。

しかし、バッファは現在 rbiot 構造体に直接埋め込まれてしまっています。
rbiot の定義を変えないと、バッファを共有させるのは難しい気がします。

rbiot は公開 API であり、etc/ 以下だけでなくいくつかの 3rd party の
拡張ライブラリで実際に使われています。下手にいじると、バイナリ互換性の
問題が起きてしまいそうです。

設計上のバグなんですが、バイナリ互換性を崩してでも修正したいほど重大な
問題ではないと思います。なので 1.9.2 では、

「IO#dup や reopen の元になった IO はもう使ってはいけない (close
しかしてはならない) 。バグだが当面 WONTFIX である。」

と宣言してしまい、いつか他の要因でバイナリ互換性を捨てる際 (遅くとも
2.0) に、あわせて修正するのがいいのではないかと思いました。

もちろん、バイナリ互換性に影響のない形で修正できるなら、それが一番いい
と思います (ただし、煩わしい workaround のせいでひどくメンテナンス性が
落ちるとしたら考えもの) 。

今考えている修正方針の案などがあれば教えてください。

--
Yusuke ENDOH mame@tsg.ne.jp

=end

#5 Updated by Yusuke Endoh almost 4 years ago

  • Status changed from Open to Rejected

=begin
遠藤です。

1.9.2 では仕様ということで reject します。( 他)

わかりにくい挙動なことは確かなので、1.9.3 以降での改善を Feature
チケットとして別に登録しておきます。

--
Yusuke Endoh mame@tsg.ne.jp
=end

Also available in: Atom PDF