From: Yusuke ENDOH Date: 2010-02-11T17:14:31+09:00 Subject: [ruby-dev:40390] Re: [Bug:trunk] TCPServer#gets gets stuck 遠藤です。 2010年2月11日16:46 Tanaka Akira : > 2010年2月9日22:23 Yusuke ENDOH : >> >> といってもこのパッチで正しいかどうかはかなり自信ないので、IO >> 周りで変とか固まるとかになったら、この件を疑ってください。 > > test-all で失敗が増えていますね。 > > % ./ruby -v test/ruby/test_io.rb > ruby 1.9.2dev (2010-02-11 trunk 26640) [i686-linux] > Loaded suite test/ruby/test_io > Started > ........................................................F.......F.................... > Finished in 1.087307 seconds. > > 1) Failure: > test_read_error(TestIO) [test/ruby/test_io.rb:869]: > RuntimeError expected but nothing was raised. > > 2) Failure: > test_readpartial_error(TestIO) [test/ruby/test_io.rb:834]: > RuntimeError expected but nothing was raised. > > 85 tests, 336 assertions, 2 failures, 0 errors, 0 skips ああそうだ、忘れてました。それが「瑣末な問題」といったやつです。 もともとは $ ruby-1.9.1-p378 -e ' r, w = IO.pipe s = "" t = Thread.new { r.read(5, s) } 0 until s.size == 5 s.clear w.write "foobarbaz" w.close t.join ' -e:4:in `read': buffer string modified (RuntimeError) from -e:4:in `block in
' のように、 - read にバッファを明示して待ち状態にし、 - バッファを modify した後で - write したら例外が上がる、 という挙動だったのですが、以下のようにすると、このチェックは 抜けられることがあります (タイミングに依存しますが) 。 $ ruby-1.9.1-p378 -e ' r, w = IO.pipe s = "" w.write "foo" t = Thread.new { r.read(5, s) } 0 until s.size >= 5 p s s.clear w.write "barbaz" w.close t.join p s ' "\x00ooba" つまり、 - read にバッファを明示して待ち状態にし、 - read 分に満たないだけ write して (これでチェックをかわせる) - バッファを modify した後で - write しても例外が上がらず変なことになる (ことがある) というわけで、このチェックには今のところ意味がないと思います。 やるとしたら、io_read の中の READ_CHECK の直後だけでチェックしても だめで、buffer string に書こうとする直前で毎回チェックする必要が あると思いますが、IO のパフォーマンスが下がりそうなのでそこまでする 必要があるかどうかはわかりません。 と言うわけで、反対がなければこのチェックとテストは外してしまおうと 思っています。 > まぁ、これは落ちなければいいという類の話で、いまのところ落ちていないので > いいといえばいいのですが、危険に近づいている気はします。 なんとかできるといいんですけどねえ。 何度も言っていますが、「安全側に倒して TCPServer#gets が固まることが あるのは仕様とする」と言ってくれるのでも私は構いません。 確かに、rubyspec の人たちも 1.8 とかで rubinius とかで固まってないの か不思議ですよね。今度聞いときます。 -- Yusuke ENDOH