Project

General

Profile

Bug #2795

readpartial after ungetc fails with text mode

Added by mame (Yusuke Endoh) almost 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
ruby 1.9.2dev (2010-04-20 trunk 27405) [i686-linux]
Backport:
[ruby-dev:40493]

Description

=begin
遠藤です。

以下のようにすると、"a" が出力されることを期待するのですが、
EOFError になります。

$ echo -n a > foo.txt && ./ruby -e '
open("foo.txt", "r+t") do |f|
f.ungetc(f.getc)
p f.readpartial(2)
end
'
-e:4:in readpartial': end of file reached (EOFError)
from -e:4:in
block in '
from -e:2:in open'
from -e:2:in
'

mingw32 での rubyspec がこのせいで固まるようです (mingw32
だと "r+" だけで問題になる) 。

こういう顛末みたいです。

  1. text mode だと ungetc が rbuf でなく cbuf に記録する
  2. readpartial は rbuf しか見ない

readpartial が cbuf も見るべきなんですかね。

これは akr さんか成瀬さんの担当でいいでしょうか。

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

History

#1

Updated by mame (Yusuke Endoh) almost 10 years ago

=begin
遠藤です。

2010年2月26日19:42 Tanaka Akira akr@fsij.org:

2010年2月26日19:34 Yusuke ENDOH mame@tsg.ne.jp:

  1. text mode だと ungetc が rbuf でなく cbuf に記録する
  2. readpartial は rbuf しか見ない

readpartial が cbuf も見るべきなんですかね。

いいえ。

cbuf は文字コード変換済みのデータを貯めておく場所であり、
readpartial は変換前のバイト列を読み出すメソッドなので、
cbuf を読まないのは正しい動作です。

うう、1.9 の IO は本当に難しいですね。

IO#readpartial と ungetc の rdoc をぱっと見ても "buffer" の種類が
複数あるとは読み取れなかったのですが、どこかに書いてあることですか?
バッファリングしているとかユーザが気にしなくてもいいようにならない
ものかなあ。

とりあえず、RubySpec 側で pipe を binmode にしてしのぎます。

--
Yusuke ENDOH mame@tsg.ne.jp

=end

#2

Updated by kosaki (Motohiro KOSAKI) almost 10 years ago

=begin
2010年2月26日20:19 Yusuke ENDOH mame@tsg.ne.jp:

遠藤です。

2010年2月26日19:42 Tanaka Akira akr@fsij.org:

2010年2月26日19:34 Yusuke ENDOH mame@tsg.ne.jp:

  1. text mode だと ungetc が rbuf でなく cbuf に記録する
  2. readpartial は rbuf しか見ない

readpartial が cbuf も見るべきなんですかね。

いいえ。

cbuf は文字コード変換済みのデータを貯めておく場所であり、
readpartial は変換前のバイト列を読み出すメソッドなので、
cbuf を読まないのは正しい動作です。

うう、1.9 の IO は本当に難しいですね。

IO#readpartial と ungetc の rdoc をぱっと見ても "buffer" の種類が
複数あるとは読み取れなかったのですが、どこかに書いてあることですか?
バッファリングしているとかユーザが気にしなくてもいいようにならない
ものかなあ。

この問題が表面化するのはungetc()だけなので、バッファが2つあるという実装を書く必要はなくて
ungetc()のメソッドの説明にバイナリ読み込みと組み合わせたら結果は不定だよ。と
追記すれば済む話ではないかなぁ

現実世界で、そういう要望はこなさそうだし。

とりあえず、RubySpec 側で pipe を binmode にしてしのぎます。

=end

#3

Updated by kosaki (Motohiro KOSAKI) almost 10 years ago

=begin
2010年2月27日0:10 Tanaka Akira akr@fsij.org:

2010年2月26日20:19 Yusuke ENDOH mame@tsg.ne.jp:

IO#readpartial と ungetc の rdoc をぱっと見ても "buffer" の種類が
複数あるとは読み取れなかったのですが、どこかに書いてあることですか?

readpartial というよりは、バイト単位のサイズを指定するメソッドは
基本的にバイト列レベルで動作するという、より一般的な話なんですが、
書いてあったかなぁ。

http://doc.okkez.net/static/191/class/IO.html

の「エンコーディングの影響を受けるメソッドと受けないメソッド」に分類が書いてあるのですが、
ungetc()のようなバイナリ読み込みメソッドに対して副作用があるメソッド側に、その旨の
記載がないのが問題という認識でいるのですが・・・

バッファリングしているとかユーザが気にしなくてもいいようにならない
ものかなあ。

そのこと自体は良いと思うので、そのためにできることを思いついて、
害が無ければ、実装して入れていくのがいいんじゃないですかね。

完璧にやるのは無理だと思うんですが。

[田中 哲][たなか あきら][Tanaka Akira]

=end

#4

Updated by mame (Yusuke Endoh) almost 10 years ago

  • Assignee set to akr (Akira Tanaka)
  • Target version set to 1.9.2
  • ruby -v set to ruby 1.9.2dev (2010-04-20 trunk 27405) [i686-linux]

=begin
akr さん
遠藤です。

この挙動は by design ということですが、IO#ungetc の rdoc に

Pushes back one character (passed as a parameter) onto ios,
such that a subsequent buffered read will return it.

と書いてあり、かつ IO#readpartial の rdoc に

If the buffer is not empty, read from the buffer instead of
"sysread for buffered IO (IOError)".

と書いてあるので、rdoc が間違っているか、または非常にわかりにくい
と思います。

IO の rdoc には手が出せない (仕様は akr さんの頭の中にしかない
ような気がする) ので、修正していただけませんでしょうか。
この修正を以てこのチケットを閉じる、ということでどうでしょう。

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

#5

Updated by akr (Akira Tanaka) over 9 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r27470.
Yusuke, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF