Bug #5355
closedSync_mにBug #5195やBug #5258と同様のバグ
Description
=begin
Sync_mにもBug #5195やBug #5258と同様のバグがあります。
require 'sync'
class Foo; include Sync_m; end
foo = Foo.new
foo.sync_lock(:EX)
t = Thread.new { foo.sync_lock(:EX) }
nil until t.stop?
p foo.sync_waiting
t.wakeup
nil until t.stop?
p foo.sync_waiting
上記のコードを実行すると
[#<Thread:0x00000001936858 sleep>]
[#<Thread:0x00000001936858 sleep>, #<Thread:0x00000001936858 sleep>]
このように、起こされた際に@sync_waitingに再度Thread.currentをpushしてしまいます。
また、次のコードを実行すると、
require 'sync'
class Foo; include Sync_m; end
foo = Foo.new
foo.sync_lock(:SH)
t = Thread.start do
foo.sync_lock(:SH)
foo.sync_lock(:EX)
end
nil until t.stop?
p foo.sync_upgrade_waiting
p foo.sync_waiting
t.wakeup
nil until t.stop?
p foo.sync_upgrade_waiting
p foo.sync_waiting
このような結果となります。
#<Thread:0x000000015e04d8 sleep>, 1
[]
#<Thread:0x000000015e04d8 sleep>, 1
[#<Thread:0x000000015e04d8 sleep>]
複数のスレッドが共有ロックを保持している時にあるスレッドが共有ロックから排他ロックへ昇格しようとした場合、
共有ロックの開放を待つスレッドは@sync_upgrade_waitingにpushされますが、この状態からそのスレッドを起こすと、
@sync_upgrade_waitingではなく@sync_waitingにThread.currentがpushされます。
また、 http://redmine.ruby-lang.org/issues/5258#note-2 と同様の問題ですが、ロックの開放待ちで寝ているスレッドに例外を発生させると、
@waitingにpushされたスレッドはそのまま放置されてしまいます。
require 'sync'
class Foo; include Sync_m; end
foo = Foo.new
foo.sync_lock(:EX)
t = Thread.new { foo.sync_lock(:EX) }
nil until t.stop?
p foo.sync_waiting
t.raise
nil while t.alive?
p foo.sync_waiting
実行結果:
[#<Thread:0x00000000e498f0 sleep>]
[#<Thread:0x00000000e498f0 dead>]
以上の問題を解決するpatchを添付します。
=end
Files
Updated by ayumin (Ayumu AIZAWA) almost 13 years ago
- Assignee set to kosaki (Motohiro KOSAKI)
#5258 とおなじく小崎さんにAssignしますよ
Updated by kosaki (Motohiro KOSAKI) almost 13 years ago
スレッドまわりは振ってくれていいですよ。ほかに誰も見てくれなさそうだし。ただあからさまに優先度低そうなやつは暇なときかリリース近いときしか作業できませぬ
Updated by shyouhei (Shyouhei Urabe) almost 13 years ago
- Status changed from Open to Assigned
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r36936.
Masaki, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
-
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.
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
これも #5195と同じく timeout moduleが予期せぬタイミングでexception投げるケースを考えると ensure節を1つ足しただけではなにも解決してないのですが、悪化することはないので入れます