Bug #5355

Sync_mにBug #5195やBug #5258と同様のバグ

Added by Masaki Matsushita over 3 years ago. Updated over 2 years ago.

[ruby-dev:44521]
Status:Closed
Priority:Normal
Assignee:Motohiro KOSAKI
ruby -v:ruby 1.9.4dev (2011-09-20 trunk 33301) [x86_64-linux] Backport:

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

上記のコードを実行すると

[#]
[#, #]

このように、起こされた際に@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

このような結果となります。

#, 1
[]
#, 1
[#]

複数のスレッドが共有ロックを保持している時にあるスレッドが共有ロックから排他ロックへ昇格しようとした場合、
共有ロックの開放を待つスレッドは@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

実行結果:

[#]
[#]

以上の問題を解決するpatchを添付します。

=end

patch.diff Magnifier (1.16 KB) Masaki Matsushita, 09/23/2011 11:53 AM


Related issues

Related to Ruby trunk - Bug #5195: Queue#popでsleepしているthreadをwakeupさせるとQueueの@waitingにそのthreadがpushされてしまう Closed 08/16/2011
Related to Ruby trunk - Bug #5258: SizedQueueにBug #5195と同様のバグ Closed 09/01/2011
Duplicated by Ruby trunk - Bug #6911: Sync_m#sync_unlock で ThreadError が発生する場合がある Closed 08/23/2012

Associated revisions

Revision 36936
Added by Motohiro KOSAKI over 2 years ago

  • lib/sync.rb (Sync_m#sync_lock): Fixed wakeup/raise unsafe code.
    Patched by Masaki Matsushita. [Bug #5355]

  • test/thread/test_sync.rb (test_sync_lock_and_wakeup,
    test_sync_upgrade_and_wakeup, test_sync_lock_and_raise):
    new test.

Revision 36936
Added by Motohiro KOSAKI over 2 years ago

  • lib/sync.rb (Sync_m#sync_lock): Fixed wakeup/raise unsafe code.
    Patched by Masaki Matsushita. [Bug #5355]

  • test/thread/test_sync.rb (test_sync_lock_and_wakeup,
    test_sync_upgrade_and_wakeup, test_sync_lock_and_raise):
    new test.

History

#1 Updated by Ayumu AIZAWA over 3 years ago

  • Assignee set to Motohiro KOSAKI

#5258 とおなじく小崎さんにAssignしますよ

#2 Updated by Motohiro KOSAKI over 3 years ago

スレッドまわりは振ってくれていいですよ。ほかに誰も見てくれなさそうだし。ただあからさまに優先度低そうなやつは暇なときかリリース近いときしか作業できませぬ

#3 Updated by Shyouhei Urabe about 3 years ago

  • Status changed from Open to Assigned

#4 Updated by Motohiro KOSAKI over 2 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]

  • test/thread/test_sync.rb (test_sync_lock_and_wakeup,
    test_sync_upgrade_and_wakeup, test_sync_lock_and_raise):
    new test.

#5 Updated by Motohiro KOSAKI over 2 years ago

これも #5195と同じく timeout moduleが予期せぬタイミングでexception投げるケースを考えると ensure節を1つ足しただけではなにも解決してないのですが、悪化することはないので入れます

Also available in: Atom PDF