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

ruby-changes:24884

From: kosaki <ko1@a...>
Date: Sun, 9 Sep 2012 20:34:57 +0900 (JST)
Subject: [ruby-changes:24884] kosaki:r36936 (trunk): * lib/sync.rb (Sync_m#sync_lock): Fixed wakeup/raise unsafe code.

kosaki	2012-09-09 20:34:47 +0900 (Sun, 09 Sep 2012)

  New Revision: 36936

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36936

  Log:
    * lib/sync.rb (Sync_m#sync_lock): Fixed wakeup/raise unsafe code.
      Patched by Masaki Matsushita. [Bug #5355] [ruby-dev:44521]
    
    * test/thread/test_sync.rb (test_sync_lock_and_wakeup,
      test_sync_upgrade_and_wakeup, test_sync_lock_and_raise):
      new test.

  Added files:
    trunk/test/thread/test_sync.rb
  Modified files:
    trunk/ChangeLog
    trunk/lib/sync.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36935)
+++ ChangeLog	(revision 36936)
@@ -1,3 +1,12 @@
+Sun Sep  9 20:20:31 2012  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* lib/sync.rb (Sync_m#sync_lock): Fixed wakeup/raise unsafe code.
+	  Patched by Masaki Matsushita. [Bug #5355] [ruby-dev:44521]
+
+	* test/thread/test_sync.rb (test_sync_lock_and_wakeup,
+	  test_sync_upgrade_and_wakeup, test_sync_lock_and_raise):
+	  new test.
+
 Sun Sep  9 18:39:46 2012  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* include/ruby/intern.h (rb_thread_blocking_region): Added
Index: lib/sync.rb
===================================================================
--- lib/sync.rb	(revision 36935)
+++ lib/sync.rb	(revision 36936)
@@ -138,16 +138,22 @@
 
     while true
       @sync_mutex.synchronize do
-        if sync_try_lock_sub(m)
-          return self
-        else
-          if sync_sh_locker[Thread.current]
-            sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
-            sync_sh_locker.delete(Thread.current)
+        begin
+          if sync_try_lock_sub(m)
+            return self
           else
-            sync_waiting.push Thread.current
+            if sync_sh_locker[Thread.current]
+              sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
+              sync_sh_locker.delete(Thread.current)
+            else
+              unless sync_waiting.include?(Thread.current) || sync_upgrade_waiting.reverse_each.any?{|w| w.first == Thread.current }
+                sync_waiting.push Thread.current
+              end
+            end
+            @sync_mutex.sleep
           end
-          @sync_mutex.sleep
+        ensure
+          sync_waiting.delete(Thread.current)
         end
       end
     end
Index: test/thread/test_sync.rb
===================================================================
--- test/thread/test_sync.rb	(revision 0)
+++ test/thread/test_sync.rb	(revision 36936)
@@ -0,0 +1,57 @@
+require 'test/unit'
+require 'sync'
+require 'timeout'
+
+class SyncTest < Test::Unit::TestCase
+  class Tester
+    include Sync_m
+  end
+
+  def test_sync_lock_and_wakeup
+    tester = Tester.new
+
+    tester.sync_lock(:EX)
+
+    t = Thread.new { tester.sync_lock(:EX) }
+
+    sleep 0.1 until t.stop?
+    t.wakeup
+    sleep 0.1 until t.stop?
+
+    assert_equal(tester.sync_waiting.uniq, tester.sync_waiting)
+  end
+
+  def test_sync_upgrade_and_wakeup
+    tester = Tester.new
+    tester.sync_lock(:SH)
+
+    t = Thread.new do
+      tester.sync_lock(:SH)
+      tester.sync_lock(:EX)
+    end
+
+    sleep 0.1 until t.stop?
+    t.wakeup
+    sleep 0.1 until t.stop?
+
+    tester.sync_upgrade_waiting.each { |ary|
+      assert(!tester.sync_waiting.include?(ary[0]))
+    }
+    assert_equal(tester.sync_waiting.uniq, tester.sync_waiting)
+    assert_equal(tester.sync_waiting, [])
+  end
+
+  def test_sync_lock_and_raise
+    tester= Tester.new
+    tester.sync_lock(:EX)
+
+    t = Thread.new { tester.sync_lock(:EX) }
+
+    sleep 0.1 until t.stop?
+    t.raise
+    sleep 0.1 while t.alive?
+
+    assert_equal(tester.sync_waiting.uniq, tester.sync_waiting)
+    assert_equal(tester.sync_waiting, [])
+  end
+end

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

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