[#43465] GVL改善案 — KOSAKI Motohiro <kosaki.motohiro@...>
小崎です
[#43467] [Q] thread->interrupt_flag が適切に排他制御されていないように見える — KOSAKI Motohiro <kosaki.motohiro@...>
kosakiです
ささだです.
> ささだです.
ささだです.
> ささだです.
自己解決しました
ささだです.
>> ということは危ないのは RUBY_VM_SET_INTERRUPT() がロストしたときに、タイムアウトなしの
>>> ということは危ないのは RUBY_VM_SET_INTERRUPT() がロストしたときに、タイムアウトなしの
[#43468] Re: [ruby-changes:19438] Ruby:r31478 (trunk): * test/date/*.rb: use skip /w messages. — KOSAKI Motohiro <kosaki.motohiro@...>
2011/5/8 tadf <[email protected]>:
> 表示したい場合を除いてはskipよりもreturnを使うようお願いしています。
>> 表示したい場合を除いてはskipよりもreturnを使うようお願いしています。
[#43476] [Ruby 1.9 - Feature #4653][Open] [PATCH 1/1] new method Enumerable#rude_map — Shyouhei Urabe <shyouhei@...>
遠藤です。
(05/08/2011 11:21 PM), Yusuke ENDOH wrote:
遠藤です。
卜部です。
At Mon, 9 May 2011 16:35:31 +0900,
遠藤です。
[#43493] [Ruby 1.9 - Feature #4657][Open] add option to hide skip messages on unit/test — Shota Fukumori <sorah@...>
> -q, --hide-skipでskipメッセージが表示されなくなります。
(05/09/2011 06:31 PM), Shota Fukumori wrote:
> (05/09/2011 06:31 PM), Shota Fukumori wrote:
2011/5/9 KOSAKI Motohiro <[email protected]>:
> 2011/5/9 KOSAKI Motohiro <[email protected]>:
[#43502] draft schedule of Ruby 1.9.3 — "Yuki Sonoda (Yugui)" <yugui@...>
-----BEGIN PGP SIGNED MESSAGE-----
Hi
Hello,
(ruby-coreはずしました)
こんにちは、なかむら(う)です。
こんにちは、なかむら(う)です。
[#43549] RubyKaigi2011に'CRuby'コミッタの皆さまを招待いたします(締切:2011-06-15) — Kakutani Shintaro <shintaro.kakutani@...>
'CRuby'コミッタの皆さまへ
[#43554] [Ruby 1.9 - Bug #4696][Assigned] thread.c#lock_func() が spurious wakeup unsafe — Motohiro KOSAKI <kosaki.motohiro@...>
[#43606] [Ruby 1.9 - Bug #4808][Open] thread_wait_for() eats 100% of CPU power — Hidetoshi Nagai <nagai@...>
> いつからかは把握できていませんが (少なくとも 1.9.2p0 では発生しません),
[ruby-dev:43554] [Ruby 1.9 - Bug #4696][Assigned] thread.c#lock_func() が spurious wakeup unsafe
Issue #4696 has been reported by Motohiro KOSAKI.
----------------------------------------
Bug #4696: thread.c#lock_func() が spurious wakeup unsafe
http://redmine.ruby-lang.org/issues/4696
Author: Motohiro KOSAKI
Status: Assigned
Priority: Low
Assignee: Motohiro KOSAKI
Category: core
Target version: 1.9.3
ruby -v: ruby 1.9.3dev (2011-05-13 trunk 31548) [x86_64-linux]
レビューをしていて、気づいたので起票します。
現在の lock_func (ie Mutex.lockの実体)は以下のような構造になっています
(本質的ではない部分をカットしてあります)
------------------------------------------------------------------------
static int
lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
{
for (;;) {
if (!mutex->th) {
mutex->th = th;
break;
}
mutex->cond_waiting++;
if (timeout_ms) {
ret = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
if (ret == ETIMEDOUT) {
interrupted = 2;
mutex->cond_waiting--;
break;
}
}
else {
native_cond_wait(&mutex->cond, &mutex->lock);
}
mutex->cond_notified--;
if (RUBY_VM_INTERRUPTED(th)) {
interrupted = 1;
break;
}
}
return interrupted;
}
------------------------------------------------------------------------
以下の2つの問題点があります。
1) native_cond_wait() が spurious wakeupで起床したばあい、誰もnative_cond_signal()を
呼んでいないにもかかわらず cond_notified がデクリメントされてしまう。
結果、以後デッドロックチェックが誤動作する
2) pthread_cond_timedwait()で寝ているスレッドが、pthread_cond_signal()にて起床させられ、
*かつ*、コンテキススイッチやらなにやらしている間にタイムアウト時間も過ぎてしまった場合
戻り値が0になるかETIMEOUTになるかはプラットフォーム依存。この場合にETIMEOUTを返す
プラットフォーム上で、復帰値のETIMEOUTを信用するとやはり mutex->cond_waiting がずれてしまう。
対策としては、さきにcond waitが暗に持っているpredicate(この場合は mutex->th と
RUBY_VM_INTERRUPTED のチェックを最初におこない、それが終わってからETIMEOUTチェックを
することで、プラットフォームの影響を避けられます。
(1)は deadlock checkマージ時からの障害なんですが、YARVマージ時点ですでに
mutex->cond_waiting がずれる問題はあって、それを顕在化させる方法がなかったという理解
(2)はpthread_cond_timedwitを使うようにした r31373 からの障害
結局最大の問題はspurious wakeupがある以上、native_cond_signal()を呼ぶ回数とwakeupの回数は
一致する保証はないのだから、カウンタをcond_signal時に+1してwakeupしたときに-1する設計は
無理があるということです。
で、さらによくよく考えてみるとdeadlockの設計はもっと簡単に出来ることが分かりました。
lock_func内でunlock待ちで滞留しているスレッドの数は簡単にカウントできるのだから、
mutex->thがNULLで滞留スレッドが0じゃなければ、過度期状態ということでしょう。
パッチを作ってみたところ、添付のようにかなり小さい修正で対応できることが分かったので
取り込み可能と思いますが、1−2週間まってささださんやまめさんが反対するなら流産にさせようと
思います。
なお、軽く各プラットフォームの状況を聞いたり調べた感じだと以下のような状況
・Linux
pthread_cond_wait()がglibc内でspurious wakeup対応があるので、アプリケーションからは
spurious wakeupは見えない。linux thread だとシグナル受けるとEINTRで復帰してしまうバグが
あるが、それは thread_pthread.c#native_cond_wait() で塞いである(r31482)ので影響を与えない。
pthread_cond_timedwait()の復帰値はバージョンによって異なり、初期のglibcは0を返したが
最近のはわざわざシステムコールから復帰したあとに、clock_gettime()で時間をチェックして
時間超過していた場合は復帰値をETIMEOUTに差し替える処理が追加されており問題が起こる
(余計なことを・・・)
・NetBSD
上記状況で、pthread_cond_timedwait()がETIMEOUTを返す仕様であると、聞いたことがあります。
・Mac
なんと、スレッドがシグナルと受けると cond_wait()が0を復帰値にして返ってくると言う
トンデモ仕様だそうです。
--
http://redmine.ruby-lang.org