ruby-changes:49158
From: nobu <ko1@a...>
Date: Fri, 15 Dec 2017 16:27:09 +0900 (JST)
Subject: [ruby-changes:49158] nobu:r61274 (trunk): thread.c: fix deadlock
nobu 2017-12-15 16:27:04 +0900 (Fri, 15 Dec 2017) New Revision: 61274 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61274 Log: thread.c: fix deadlock * thread.c (thread_join_sleep): the target thread may exit during `RUBY_VM_CHECK_INTS_BLOCKING`, but `sleep_forever` does not consider the condition change to wait. [ruby-core:84248] [Bug #14181] Modified files: trunk/test/ruby/test_thread.rb trunk/thread.c Index: test/ruby/test_thread.rb =================================================================== --- test/ruby/test_thread.rb (revision 61273) +++ test/ruby/test_thread.rb (revision 61274) @@ -1249,4 +1249,42 @@ q.pop https://github.com/ruby/ruby/blob/trunk/test/ruby/test_thread.rb#L1249 end _end end + + def test_signal_at_join + if /mswin|mingw/ =~ RUBY_PLATFORM + skip "can't trap a signal from another process on Windows" + # opt = {new_pgroup: true} + end + assert_separately([], "#{<<~"{#"}\n#{<<~'};'}") + {# + n = 1000 + sig = :INT + trap(sig) {} + IO.popen([EnvUtil.rubybin, "-e", "#{<<~"{#1"}\n#{<<~'};#1'}"], "r+") do |f| + tpid = #{$$} + sig = :#{sig} + {#1 + STDOUT.sync = true + while gets + puts + Process.kill(sig, tpid) + end + };#1 + assert_nothing_raised do + n.times do + w = Thread.start do + sleep 30 + end + begin + f.puts + f.gets + ensure + w.kill + w.join + end + end + end + end + }; + end end Index: thread.c =================================================================== --- thread.c (revision 61273) +++ thread.c (revision 61274) @@ -883,7 +883,13 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L883 while (target_th->status != THREAD_KILLED) { if (forever) { - sleep_forever(th, TRUE, FALSE); + th->status = THREAD_STOPPED_FOREVER; + th->vm->sleeper++; + rb_check_deadlock(th->vm); + native_sleep(th, 0); + th->vm->sleeper--; + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + th->status = THREAD_RUNNABLE; } else { double now = timeofday(); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/