From: Nobuyoshi Nakada Date: 2011-12-20T15:57:20+09:00 Subject: [ruby-dev:45013] Re: [ruby-trunk - Bug #5768] TestRequire#test_race_exceptionで競合するケースがまだある なかだです。 (11/12/20 13:43), Yui NARUSE wrote: > 追いかけた結果、どうも lock に用いている rb_barrier_release/rb_barrier_destroy や rb_mutex_lock のマルチスレッド対応がいまいちだったようです。 > 前者は rb_mutex_unlock を外した直後から、待っていた他のスレッドが動き始めるのでもはや mutex->cond_waiting は古い情報となってしまう点、 > 後者は GVL_UNLOCK_BEGIN() した直後から、メインのスレッドが動いてしまう可能性があるのがダメですね。 たしかに、rb_mutex_lockがGVLを先に開放していることを見落としていました。 rb_barrier_release/rb_barrier_destroyが呼ばれた時点ではmutexがロックさ れていることが前提ですので、後半のBarrier部分の変更だけで充分な気がしま す。 > diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb > index 9186a6f..f1d8d12 100644 > --- a/test/ruby/test_require.rb > +++ b/test/ruby/test_require.rb > @@ -350,9 +350,18 @@ class TestRequire < Test::Unit::TestCase > path = tmp.path > tmp.print <<-EOS > TestRequire.scratch << :pre > -Thread.pass until t2 = TestRequire.scratch[1] > +TestRequire.scratch << Thread.current > +Thread.pass until t2 = TestRequire.scratch[2] > Thread.pass until t2.stop? > -open(__FILE__, "w") {|f| f.puts "TestRequire.scratch << :post"} > +open(__FILE__, "w") do |f| > + f.puts "t1, t2 = TestRequire.scratch[1, 2]" > + f.puts "if Thread.current == t2" > + f.puts " TestRequire.scratch << :post" > + f.puts " until t1.stop?" > + f.puts " Thread.pass" > + f.puts " end" > + f.puts "end" > +end > raise "con1" この変更ではt2でロードされることを想定していますが、最初のrequireが例外 で中断したあとにt1,t2のどちらが実際にロードすることになるかは不定のはず です。 -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦