[前][次][番号順一覧][スレッド一覧]

ruby-changes:53843

From: shugo <ko1@a...>
Date: Wed, 28 Nov 2018 10:51:49 +0900 (JST)
Subject: [ruby-changes:53843] shugo:r66061 (trunk): lib/monitor.rb: avoid race conditions by Thread.handle_interrupt

shugo	2018-11-28 10:51:44 +0900 (Wed, 28 Nov 2018)

  New Revision: 66061

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66061

  Log:
    lib/monitor.rb: avoid race conditions by Thread.handle_interrupt
    
    Suggested by Benoit Daloze.  [ruby-core:88502] [Bug #14998]

  Modified files:
    trunk/lib/monitor.rb
    trunk/test/monitor/test_monitor.rb
Index: test/monitor/test_monitor.rb
===================================================================
--- test/monitor/test_monitor.rb	(revision 66060)
+++ test/monitor/test_monitor.rb	(revision 66061)
@@ -269,4 +269,26 @@ class TestMonitor < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/monitor/test_monitor.rb#L269
 #     end
 #     cumber_thread.kill
   end
+
+  def test_wait_interruption
+    queue = Queue.new
+    cond = @monitor.new_cond
+    @monitor.define_singleton_method(:mon_enter_for_cond) do |*args|
+      queue.deq
+      super(*args)
+    end
+    th = Thread.start {
+      @monitor.synchronize do
+        begin
+          cond.wait(0.1)
+        rescue Interrupt
+          @monitor.instance_variable_get(:@mon_owner)
+        end
+      end
+    }
+    sleep(0.1)
+    th.raise(Interrupt)
+    queue.enq(nil)
+    assert_equal th, th.value
+  end
 end
Index: lib/monitor.rb
===================================================================
--- lib/monitor.rb	(revision 66060)
+++ lib/monitor.rb	(revision 66061)
@@ -103,13 +103,17 @@ module MonitorMixin https://github.com/ruby/ruby/blob/trunk/lib/monitor.rb#L103
     # even if no other thread doesn't signal.
     #
     def wait(timeout = nil)
-      @monitor.__send__(:mon_check_owner)
-      count = @monitor.__send__(:mon_exit_for_cond)
-      begin
-        @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
-        return true
-      ensure
-        @monitor.__send__(:mon_enter_for_cond, count)
+      Thread.handle_interrupt(Exception => :never) do
+        @monitor.__send__(:mon_check_owner)
+        count = @monitor.__send__(:mon_exit_for_cond)
+        begin
+          Thread.handle_interrupt(Exception => :immediate) do
+            @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
+          end
+          return true
+        ensure
+          @monitor.__send__(:mon_enter_for_cond, count)
+        end
       end
     end
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]