Bug #2795
readpartial after ungetc fails with text mode
| Status: | Closed | Start date: | ||
|---|---|---|---|---|
| Priority: | Low | Due date: | ||
| Assignee: | % Done: | 100% |
||
| Category: | - | |||
| Target version: | 1.9.2 | |||
| ruby -v: | ruby 1.9.2dev (2010-04-20 trunk 27405) [i686-linux] |
Description
遠藤です。
以下のようにすると、"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 <main>'
from -e:2:in `open'
from -e:2:in `<main>'
mingw32 での rubyspec がこのせいで固まるようです (mingw32
だと "r+" だけで問題になる) 。
こういう顛末みたいです。
1. text mode だと ungetc が rbuf でなく cbuf に記録する
2. readpartial は rbuf しか見ない
readpartial が cbuf も見るべきなんですかね。
これは akr さんか成瀬さんの担当でいいでしょうか。
--
Yusuke ENDOH <mame@tsg.ne.jp>
Associated revisions
* io.c: raise IOError when byte oriented operations occur with
non-empty character buffer.
[ruby-dev:40493] [ruby-dev:40506]
History
Updated by Yusuke Endoh almost 2 years ago
遠藤です。 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>
Updated by Motohiro KOSAKI almost 2 years ago
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 にしてしのぎます。
Updated by Motohiro KOSAKI almost 2 years ago
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] > >
Updated by Yusuke Endoh almost 2 years ago
- Assignee set to Akira Tanaka
- Target version set to 1.9.2
- ruby -v set to ruby 1.9.2dev (2010-04-20 trunk 27405) [i686-linux]
akr さん 遠藤です。 この挙動は by design ということですが、IO#ungetc の rdoc に Pushes back one character (passed as a parameter) onto <em>ios</em>, 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>
Updated by Akira Tanaka almost 2 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
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.