[#43610] Re: [ruby-list:48149] Re: requireが配列を取れたら便利だと思うんだけど.. — Hiroshi Nakamura <nakahiro@...>
cnVieS1saXN0GyRCJCskaTt9JEMkRk1oJF4kNyQ/ISMkRyRiQjMkKyRKJD0kJiEjGyhCCgoyMDEx
松田です。
卜部です
[#43620] Module#mix — Yukihiro Matsumoto <matz@...>
まつもと ゆきひろです
[#43634] [Ruby 1.9 - Bug #4835][Open] Compilation failure of ext/tk with recent ActiveTcl — Yuki Sonoda <yugui@...>
[#43643] DateTime.new! and DateTime.jd — Aaron Patterson <aaron.patterson@...>
こんにちは、アーロンです。
blocker はお前だろ。
まつもと ゆきひろです
> うーん、ただでさえ日英のコミュニケーション障壁があるのに、よ
2011/6/7 Tadayoshi Funaba <tadf@dotrb.org>:
皆さんってのに俺は入ってないみたいだな。
まつもと ゆきひろです
> Aaronが言ってる「リリース」は1.9.3のことだと思いますよ。
まつもと ゆきひろです
> Railsのリリースについては私は知りません。が、1.9.3のリリース
[#43645] Re: [ruby-core:36778] Re: 1.8.7 release next month — Urabe Shyouhei <shyouhei@...>
Moving to ruby-dev to understand strategies of backporting the Tk
永井@知能.九工大です.
卜部です。
永井@知能.九工大です.
[#43655] [Ruby 1.9 - Bug #4853][Assigned] ext/tk/extconf.rb fails on Mac OS X — Nobuyoshi Nakada <nobu@...>
[#43686] test.rb for make run — SASADA Koichi <ko1@...>
ささだです.
[#43700] [Ruby 1.9 - Bug #4866][Assigned] Macでmake checkするとIO.copy_streamでSEGV — Motohiro KOSAKI <kosaki.motohiro@...>
[#43710] Re: [ruby-changes:19939] kosaki:r31986 (trunk): * ext/tk/tcltklib.c (lib_eventloop_core): replace CHECK_INTS with — KOSAKI Motohiro <kosaki.motohiro@...>
永井さん
永井@知能.九工大です.
2011年6月12日0:00 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>:
[#43716] [Ruby 1.9 - Bug #3137] complex.rb changes exceptions of Math — Koichi Sasada <redmine@...>
[#43717] [Ruby 1.9 - Bug #3456] bisarre comma — Koichi Sasada <redmine@...>
まつもと ゆきひろです
メールにじかに反応したまつもとさんは読んでないと思うのでコメント#5を再掲
まつもと ゆきひろです
卜部です。
[#43743] [Ruby 1.9 - Feature #4871][Open] envのコンパクト化 — Kazuki Tsujimoto <kazuki@...>
[#43779] Re: [ruby-cvs:38869] nobu:r31690 (trunk): * gc.c (vm_xcalloc): use calloc provided by platforms. — Yutaka Kanemoto <kinpoco@...>
こんにちは。
金本と申します。
>> AIXでは0 size mallocでNULLが返るのでこまったことになっています。
ささだです.
[#43787] [Ruby 1.9 - Feature #4878][Open] CMath に frexp, ldexp, hypot の3関数は不要ではないか — Kenta Murata <muraken@...>
まつもと ゆきひろです
もう結論が出てしまったようですが、これは、元々 lib/complex.rb にあった
=E3=82=80=E3=82=89=E3=81=9F=E3=81=A7=E3=81=99=E3=80=82
> complex.rb をロードすると Math が CMath 相当に置き換わりますから、
=E3=82=80=E3=82=89=E3=81=9F=E3=81=A7=E3=81=99=E3=80=82
まつもと ゆきひろです
=E3=82=80=E3=82=89=E3=81=9F=E3=81=A7=E3=81=99=E3=80=82
> これに相当する事をやっているのが complex.rb なので、
遠藤です。
> 定義域を増やすだけにしよう、ということですよね。賛成です。
2011年6月14日22:17 Tadayoshi Funaba <tadf@dotrb.org>:
> 互換性がないという点では同じ話だと思うのですが……。
2011年6月14日23:02 Tadayoshi Funaba <tadf@dotrb.org>:
> いやあ、5 月末の feature freeze 時点では -2 を返していたはずなんですが、
遠藤です。
[#43791] [Ruby 1.9 - Bug #4879][Open] test_new(OpenSSL::TestPKeyRSA) fails on Win32 — Akio Tajima <artonx@...>
[#43820] mysterious hang at busy loop after system() — Tanaka Akira <akr@...>
以下のようなプログラムが手元の環境のひとつでハングします。
[#43829] [Ruby 1.9 - Bug #4891][Open] Vector#normalize — Kenta Murata <muraken@...>
[#43852] [Ruby 1.9 - Bug #4909][Open] trapハンドラは再入されてはいけないのではないか? — Motohiro KOSAKI <kosaki.motohiro@...>
同意します。
[#43859] [Ruby 1.9 - Bug #4911][Open] timer_thread_function() が thead unsafe — Motohiro KOSAKI <kosaki.motohiro@...>
[#43861] Date/DateTimeの仕様について — "NARUSE, Yui" <naruse@...>
ふなばさん
[#43869] [Ruby 1.9 - Bug #4919][Open] OpenSSL::SSL::Sesssion#time= に Bignum を渡すと ArgumentError が発生する — Tomoyuki Chikanaga <nagachika00@...>
報告ありがとうございます。32bit環境で落ちるとか考えてませんでした。。。
[#43875] [Ruby 1.9 - Feature #4921][Assigned] Remove intern.h — Yui NARUSE <redmine@...>
[#43890] [Ruby 1.9 - Bug #4072] dRubyで作成したサーバプログラムがsleepしていてもexitしてしまう — Tomoyuki Chikanaga <nagachika00@...>
[#43902] [Ruby 1.9 - Bug #4926][Open] --gc-stress付きtest/ruby/enc/test_emoji.rbが失敗する — Kazuki Tsujimoto <kazuki@...>
[#44001] socket related errors on chkbuild — SASADA Koichi <ko1@...>
ささだです.
[ruby-dev:43834] new deadlock detection
ささだです.
デッドロック検出をする方法を新しく実装してみました.test-all が通った
ので,添付してお送りします.
方針:
- sleeper の増減を,「スレッドを起こす人」にさせるようにした.
- デッドロックの検出を,living thread num と sleeper の比較
だけで済むようにした.
利点:
- deadlock 検出のコードが随分と綺麗になった.
まずそうなところ:
- THREAD_INTERRUPTED という状態を用意したので,意図しない
影響が出るかもしれない.
- rb_threadptr_interrupt で th->status を変えているが,
race がおきそう...(この関数は GVL 外からも呼ばれる可能性がある).
→ スレッドの状態遷移について,
しっかりとドキュメント化する必要がある
微妙なところ:
- あまり速くはならなかった,というか若干遅くなった
(現在のが十分速い,という)
前 後
vm4_thread_mutex1 0.486 0.516
vm4_thread_mutex2 0.484 0.519
vm4_thread_mutex3 0.720 0.746
(シンプルになったんで,速くなるかなぁ,と期待したんだけど.polling のほ
うが速いってことか?)
1.9.3 には怖くて入れられないような気がしますが,今後はこっちのほうが,
見通しが良くていいんでないか,という気がします.今のは難しいなぁ,とか.
--
// SASADA Koichi at atdot dot net
Attachments (1)
Index: vm_core.h
===================================================================
--- vm_core.h (revision 32131)
+++ vm_core.h (working copy)
@@ -359,6 +359,7 @@ enum rb_thread_status {
THREAD_RUNNABLE,
THREAD_STOPPED,
THREAD_STOPPED_FOREVER,
+ THREAD_INTERRUPTED,
THREAD_KILLED
};
Index: thread.c
===================================================================
--- thread.c (revision 32131)
+++ thread.c (working copy)
@@ -300,6 +300,12 @@ rb_threadptr_interrupt(rb_thread_t *th)
else {
/* none */
}
+
+ if (th->status == THREAD_STOPPED_FOREVER) {
+ th->vm->sleeper--;
+ }
+ th->status = THREAD_INTERRUPTED;
+
native_mutex_unlock(&th->interrupt_lock);
}
@@ -846,9 +852,7 @@ sleep_forever(rb_thread_t *th, int deadl
rb_check_deadlock(th->vm);
}
native_sleep(th, 0);
- if (deadlockable) {
- th->vm->sleeper--;
- }
+
RUBY_VM_CHECK_INTS();
} while (th->status == THREAD_STOPPED_FOREVER);
th->status = prev_status;
@@ -1317,7 +1321,7 @@ rb_threadptr_execute_interrupts_rec(rb_t
rb_exc_raise(err);
}
}
- th->status = status;
+ // th->status = status;
if (finalizer_interrupt) {
rb_gc_finalize_deferred();
@@ -1899,6 +1903,8 @@ thread_status_name(enum rb_thread_status
case THREAD_STOPPED:
case THREAD_STOPPED_FOREVER:
return "sleep";
+ case THREAD_INTERRUPTED:
+ return "interrupted";
case THREAD_TO_KILL:
return "aborting";
case THREAD_KILLED:
@@ -2965,7 +2971,7 @@ rb_threadptr_check_signal(rb_thread_t *m
thread_debug("main_thread: %s, sig: %d\n",
thread_status_name(prev_status), sig);
mth->exec_signal = sig;
- if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
+ // if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
rb_threadptr_interrupt(mth);
mth->status = prev_status;
}
@@ -3448,12 +3454,26 @@ rb_mutex_trylock(VALUE self)
return locked;
}
+static void
+lock_interrupt(void *ptr)
+{
+ rb_mutex_t *mutex = (rb_mutex_t *)ptr;
+
+ native_mutex_lock(&mutex->lock);
+ {
+ if (mutex->cond_waiting > 0) {
+ native_cond_broadcast(&mutex->cond);
+ }
+ }
+ native_mutex_unlock(&mutex->lock);
+}
+
static int
-lock_func(rb_thread_t *th, rb_mutex_t *mutex, int timeout_ms)
+lock_func(rb_thread_t *th, rb_mutex_t *mutex)
{
int interrupted = 0;
- int err = 0;
+ native_mutex_lock(&mutex->lock);
mutex->cond_waiting++;
for (;;) {
if (!mutex->th) {
@@ -3464,40 +3484,15 @@ lock_func(rb_thread_t *th, rb_mutex_t *m
interrupted = 1;
break;
}
- if (err == ETIMEDOUT) {
- interrupted = 2;
- break;
- }
- if (timeout_ms) {
- struct timespec timeout_rel;
- struct timespec timeout;
-
- timeout_rel.tv_sec = 0;
- timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
- timeout = native_cond_timeout(&mutex->cond, timeout_rel);
- err = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
- }
- else {
native_cond_wait(&mutex->cond, &mutex->lock);
- err = 0;
- }
}
mutex->cond_waiting--;
+ native_mutex_unlock(&mutex->lock);
return interrupted;
}
-static void
-lock_interrupt(void *ptr)
-{
- rb_mutex_t *mutex = (rb_mutex_t *)ptr;
- native_mutex_lock(&mutex->lock);
- if (mutex->cond_waiting > 0)
- native_cond_broadcast(&mutex->cond);
- native_mutex_unlock(&mutex->lock);
-}
-
/*
* call-seq:
* mutex.lock -> self
@@ -3519,40 +3514,29 @@ rb_mutex_lock(VALUE self)
}
while (mutex->th != th) {
- int interrupted;
enum rb_thread_status prev_status = th->status;
- int timeout_ms = 0;
struct rb_unblock_callback oldubf;
+ int interrupted;
set_unblock_function(th, lock_interrupt, mutex, &oldubf);
th->status = THREAD_STOPPED_FOREVER;
th->locking_mutex = self;
-
- native_mutex_lock(&mutex->lock);
th->vm->sleeper++;
- /*
- * Carefully! while some contended threads are in lock_func(),
- * vm->sleepr is unstable value. we have to avoid both deadlock
- * and busy loop.
- */
- if (vm_living_thread_num(th->vm) == th->vm->sleeper) {
- timeout_ms = 100;
- }
+
+ rb_check_deadlock(th->vm);
+
GVL_UNLOCK_BEGIN();
- interrupted = lock_func(th, mutex, timeout_ms);
- native_mutex_unlock(&mutex->lock);
+ {
+ interrupted = lock_func(th, mutex);
+ }
GVL_UNLOCK_END();
-
reset_unblock_function(th, &oldubf);
th->locking_mutex = Qfalse;
- if (mutex->th && interrupted == 2) {
- rb_check_deadlock(th->vm);
- }
+
if (th->status == THREAD_STOPPED_FOREVER) {
th->status = prev_status;
}
- th->vm->sleeper--;
if (mutex->th == th) mutex_locked(th, self);
@@ -3580,9 +3564,11 @@ rb_mutex_unlock_th(rb_mutex_t *mutex, rb
}
else {
mutex->th = 0;
- if (mutex->cond_waiting > 0)
+ if (mutex->cond_waiting > 0) {
+ th->vm->sleeper--;
native_cond_signal(&mutex->cond);
}
+ }
native_mutex_unlock(&mutex->lock);
@@ -4710,65 +4696,16 @@ ruby_native_thread_p(void)
return th != 0;
}
-static int
-check_deadlock_i(st_data_t key, st_data_t val, int *found)
-{
- VALUE thval = key;
- rb_thread_t *th;
- GetThreadPtr(thval, th);
-
- if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) {
- *found = 1;
- }
- else if (th->locking_mutex) {
- rb_mutex_t *mutex;
- GetMutexPtr(th->locking_mutex, mutex);
-
- native_mutex_lock(&mutex->lock);
- if (mutex->th == th || (!mutex->th && mutex->cond_waiting)) {
- *found = 1;
- }
- native_mutex_unlock(&mutex->lock);
- }
-
- return (*found) ? ST_STOP : ST_CONTINUE;
-}
-
-#ifdef DEBUG_DEADLOCK_CHECK
-static int
-debug_i(st_data_t key, st_data_t val, int *found)
-{
- VALUE thval = key;
- rb_thread_t *th;
- GetThreadPtr(thval, th);
-
- printf("th:%p %d %d", th, th->status, th->interrupt_flag);
- if (th->locking_mutex) {
- rb_mutex_t *mutex;
- GetMutexPtr(th->locking_mutex, mutex);
-
- native_mutex_lock(&mutex->lock);
- printf(" %p %d\n", mutex->th, mutex->cond_waiting);
- native_mutex_unlock(&mutex->lock);
- }
- else
- puts("");
-
- return ST_CONTINUE;
-}
-#endif
-
static void
rb_check_deadlock(rb_vm_t *vm)
{
- int found = 0;
+ int tnum = vm_living_thread_num(vm);
- if (vm_living_thread_num(vm) > vm->sleeper) return;
- if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
+ if (tnum > vm->sleeper) return;
+ if (tnum < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
- st_foreach(vm->living_threads, check_deadlock_i, (st_data_t)&found);
-
- if (!found) {
+ /* deadlock */
+ {
VALUE argv[2];
argv[0] = rb_eFatal;
argv[1] = rb_str_new2("deadlock detected");