[Ruby 1.9 - Bug #4723][Assigned] check deadlock i での transition for lockの扱いが thread unsafe

Issue #4723 has been reported by Motohiro KOSAKI.


Bug #4723: check_deadlock_i での transition_for_lockの扱いが thread unsafe

Author: Motohiro KOSAKI
Status: Assigned
Priority: Normal
Assignee: Motohiro KOSAKI
Category: core
Target version: 1.9.3
ruby -v: ruby 1.9.3dev (2011-05-13 trunk 31548) [x86_64-linux]

kosakiです。別のチケット切ります。

あと、transition_for_lock に volatile を付けるのもお願いします

これは明らかに悪い効果を及ぼしようがないので、先にコミットしました。
しかし、ご存じの通り、volatileをつけることでスレッド安全になるのは
マシンがUP(マシンにCPUが1つしかない)環境に限られており、最近は
デスクトップでもその仮定はあやしい。

というわけで、transition_for_lockを思い切って削除してしまうパッチを
作りました。設計ポイントは

・lock_func()を出るときにtransition_for_lockは元々なんの意味も無かった。lock_func出口で
GVL取れずに滞留しているときは、mutex->th や RUBY_VM_INTERRUPTED(th) を見ることで
check_deadlock_i()から状態変化が可視であった。
・元のデザインは GVLとmutex->lockを同時にとっては危ないという考えてそれを回避すべく
頑張っていたが、ソースコード全体を調査したところ、そんな事ないことが分かった
・よって、最初にGVLとmutex->lockを両方とも持っている瞬間をつくって、そこでvm->sleeper
をインクリメントすることにより、vm->sleeperはインクリメントされたが、mutex->cond_waiting
がまだインクリメントされてない瞬間が check_deadlock_i() から見える事はなくなる

どうでしょう?

Issue #4723 has been updated by Motohiro KOSAKI.

deadlock checkを入れるときの議論のURLを貼ります

http://markmail.org/message/xxlb4hnai54etixu#query:+page:1+mid:4ekc6xwdubrjno5r+state:results


Bug #4723: check_deadlock_i での transition_for_lockの扱いが thread unsafe
http://redmine.ruby-lang.org/issues/4723

Author: Motohiro KOSAKI
Status: Assigned
Priority: Normal
Assignee: Motohiro KOSAKI
Category: core
Target version: 1.9.3
ruby -v: ruby 1.9.3dev (2011-05-13 trunk 31548) [x86_64-linux]

kosakiです。別のチケット切ります。

あと、transition_for_lock に volatile を付けるのもお願いします

これは明らかに悪い効果を及ぼしようがないので、先にコミットしました。
しかし、ご存じの通り、volatileをつけることでスレッド安全になるのは
マシンがUP(マシンにCPUが1つしかない)環境に限られており、最近は
デスクトップでもその仮定はあやしい。

というわけで、transition_for_lockを思い切って削除してしまうパッチを
作りました。設計ポイントは

・lock_func()を出るときにtransition_for_lockは元々なんの意味も無かった。lock_func出口で
GVL取れずに滞留しているときは、mutex->th や RUBY_VM_INTERRUPTED(th) を見ることで
check_deadlock_i()から状態変化が可視であった。
・元のデザインは GVLとmutex->lockを同時にとっては危ないという考えてそれを回避すべく
頑張っていたが、ソースコード全体を調査したところ、そんな事ないことが分かった
・よって、最初にGVLとmutex->lockを両方とも持っている瞬間をつくって、そこでvm->sleeper
をインクリメントすることにより、vm->sleeperはインクリメントされたが、mutex->cond_waiting
がまだインクリメントされてない瞬間が check_deadlock_i() から見える事はなくなる

どうでしょう?