Feature #7505

Mutex#owned? メソッドの新設

Added by Motohiro KOSAKI over 1 year ago. Updated over 1 year ago.

[ruby-dev:46697]
Status:Closed
Priority:Normal
Assignee:Motohiro KOSAKI
Category:core
Target version:next minor

Description

以下のようなプログラムがあったとします。

Thread.asyncinterrupttiming(Object => :on_blocking) {
begin
  mutex = Mutex.new
mutex.synchronize {
sleep 1
condvar.wait mutex
 }
ensure
リソース解放したい
end
}

mutex.synchronizeの中でCtrl-cを押したとき、割り込まれる可能性のある箇所が三ヶ所あります

1) sleep
2) mutex.sleep の中のnativesleep(condvar.signal 待ち)
3) mutex.sleep の中のrb
mutex_lock(condvar.signalで起床されたが、mutexを別スレッドが使用中だったためmutex待ち)

このとき、1と2はmutexを持ったままensureに入りますが、3はmutexを持たずにensureに入ってきます。さらに悪いことに2と3はRubyからは同じメソッド内にあるため、rubyレベルで workaroundをもうけることができません。

リソースを正しく解放する手段が「ない」というのは問題であるので、Mutex#owned? メソッドの新設を提案します。これはMutex#locked? とは異なり自分がロックを持っているときのみtrueを返します

パッチは以下

https://gist.github.com/4195632

以下余談、POSIXだと、pthreadcondwaitはキャンセレーションポイントではないし、なにがあろうともMutexをlockし終わってから関数を抜けてくるのでこういう問題はありません。これに揃えるという手もあるのですが、そうすると別スレッドがロックを持ったままでいるとCtrl-Cが効かなくなるのでakrさんの好みにはあわなさそう。


Related issues

Related to ruby-trunk - Feature #6762: Control interrupt timing Closed 07/21/2012

Associated revisions

Revision 38188
Added by Motohiro KOSAKI over 1 year ago

  • thread.c (rbmutexowned_p): new method that return current thread have the target mutex or not. [Feature #7505]
  • test/ruby/testthread.rb (testmutexowned, testmutex_owned2): test for the above.
  • NEWS: new for the above.

History

#1 Updated by Masaya Tarui over 1 year ago

多分、こういう事だろうとおもうのですが、

mutex=Mutex.new
Thread.new{
mutex.synchronize{
begin
sleep 1
mutex.sleep
ensure
リソース解放
end
}
}
mutex.syncronize{
sleep 10
}

mutex.sleepでmutexを手放している間にC-cがされてmutexを確保しようとするが確保できなかったとして、
そのmutexを確保しているThreadも死なないと行けないのでいずれmutexは解放されて、
mutex.sleepの方でmutexを取れるんじゃ無いでしょうか?

なので、mutexを取れるまで待つように修正する方針を押したいと思います。
つまり、1,2,3いずれの例でもmutexを保持してensureに入るようにしたい。

#2 Updated by Motohiro KOSAKI over 1 year ago

樽井さんの例はもっと危険で mutexがunlockしたまま例外で抜けてきて synchronized抜けるときにもう一度 unlockしちゃうので、二重unlockでThreadErrorになっちゃいますね

#3 Updated by Masaya Tarui over 1 year ago

それは小崎さんの3の場合でも同じだと思うけど、
そう言う点からしても、例外で抜ける場合でmutexのlockとらないでunlockしたままとかおかしいですよね。

#4 Updated by Motohiro KOSAKI over 1 year ago

なので、mutexを取れるまで待つように修正する方針を押したいと思います。

これは個人的には賛成しますが、別チケットにすることを提案します。

#5 Updated by Masaya Tarui over 1 year ago

>> なので、mutexを取れるまで待つように修正する方針を押したいと思います。
>これは個人的には賛成しますが、別チケットにすることを提案します。
Mutex#owned? の話でしたね。すいません。
これ自体には賛成です。
ただ、これでどうして元の課題が救えるのか分かりませんでした。

#6 Updated by Motohiro KOSAKI over 1 year ago

  • Status changed from Open to Assigned
  • Assignee set to Motohiro KOSAKI

#7 Updated by Motohiro KOSAKI over 1 year ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r38188.
Motohiro, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • thread.c (rbmutexowned_p): new method that return current thread have the target mutex or not. [Feature #7505]
  • test/ruby/testthread.rb (testmutexowned, testmutex_owned2): test for the above.
  • NEWS: new for the above.

Also available in: Atom PDF