[#34647] fork 不可能な環境での test_argv0_noarg — wanabe <s.wanabe@...>

ワナベと申します。

13 messages 2008/05/11
[#34667] Re: fork 不可能な環境での test_argv0_noarg — Yukihiro Matsumoto <matz@...> 2008/05/13

まつもと ゆきひろです

[#34742] Ruby 1.8.7-preview3 has been released — "Akinori MUSHA" <knu@...>

 Ruby 1.8.7-preview3 をリリースしました。

14 messages 2008/05/18
[#34744] Re: [ruby-list:44957] Ruby 1.8.7-preview3 has been released — Takahiro Kambe <taca@...> 2008/05/19

お疲れ様です。

[#34800] Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...>

木村です。

18 messages 2008/05/22
[#34801] Re: Windows2000上でtrunkがビルドできない — "U.Nakamura" <usa@...> 2008/05/22

こんにちは、なかむら(う)です。

[#34824] Re: Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...> 2008/05/23

木村です。

[#34850] Re: Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...> 2008/05/26

木村です。

[#34854] Re: Windows2000上でtrunkがビルドできない — "U.Nakamura" <usa@...> 2008/05/26

こんにちは、なかむら(う)です。

[#34889] Ruby 1.8.7-preview4 test-all failed in OpenSSL::TestSSL — Nobuhiro IMAI <nov@...>

いまいです。

10 messages 2008/05/29

[ruby-dev:34874] Invalid read may occur when raising an exception to a thread that waits for mutex

From: "Yusuke ENDOH" <mame@...>
Date: 2008-05-28 12:42:48 UTC
List: ruby-dev #34874
遠藤です。

以下のようにするとハングすることがあります。

$ ./ruby -ve '
N = 10

m = [Mutex.new]
m.first.lock

t = Thread.new do
  begin
    m.first.lock # (1)
  rescue
    loop { } # (3)
  end
end

sleep 1
t.raise # (2)

m.clear
sleep 1
GC.start # (4)

t.raise # (5)
'
ruby 1.9.0 (2008-05-28 revision 16675) [i686-linux]
^Z


流れはこんな感じです。

- (1) でスレッド t の unblock_function が lock_interrupt に
  なり、mutex の解放待ちに入る。

- (2) でスレッド t の unblock_function (= lock_interrupt) が
  呼ばれる。

- スレッド t の unblock_function はクリアされるべきだが、
  クリアされないままスレッド t の実行は (3) に移る。

- (4) で mutex を free する (ただし環境依存) 。

- (5) でスレッド t の unblock_function (= lock_interrupt) が
  呼ばれるが、lock_interrupt の中で解放済みの mutex に触る。


実際、valgrind にかけると、lock_interrupt 内で Invalid read
しているのがわかります。

==15890== Invalid read of size 4
==15890==    at 0x811AA87: lock_interrupt (thread.c:2439)
==15890==    by 0x81181D9: rb_thread_interrupt (thread.c:222)
==15890==    by 0x8119284: rb_thread_ready (thread.c:864)
==15890==    by 0x81192EE: rb_thread_raise (thread.c:884)
==15890==    by 0x811941F: thread_raise_m (thread.c:960)
==15890==    by 0x810A59B: call_cfunc (vm_insnhelper.c:286)
==15890==    by 0x8114F32: vm_call_cfunc (vm_insnhelper.c:376)
==15890==    by 0x8114A7C: vm_call_method (vm_insnhelper.c:508)
==15890==    by 0x8110F8B: vm_eval (insns.def:1048)
==15890==    by 0x8115135: vm_eval_body (vm.c:1022)
==15890==    by 0x811575C: rb_iseq_eval (vm.c:1226)
==15890==    by 0x805A0FB: ruby_exec_node (eval.c:221)
==15890==  Address 0x44B6F04 is 76 bytes inside a block of size 80 free'd
==15890==    at 0x401CFA5: free (vg_replace_malloc.c:233)
==15890==    by 0x805EA4E: ruby_xfree (gc.c:425)
==15890==    by 0x811A899: mutex_free (thread.c:2340)
==15890==    by 0x80606C4: obj_free (gc.c:1498)
==15890==    by 0x8060214: gc_sweep (gc.c:1371)
==15890==    by 0x8060B0C: garbage_collect (gc.c:1704)
==15890==    by 0x80614AF: rb_gc (gc.c:2119)
==15890==    by 0x8060B6B: rb_gc_start (gc.c:1751)
==15890==    by 0x810A5B1: call_cfunc (vm_insnhelper.c:289)
==15890==    by 0x8114F32: vm_call_cfunc (vm_insnhelper.c:376)
==15890==    by 0x8114A7C: vm_call_method (vm_insnhelper.c:508)
==15890==    by 0x8110F8B: vm_eval (insns.def:1048)


unblock_function がクリアされないのは set_unblock_function 内で
RUBY_VM_CHECK_INTS をしていて、そこから longjmp するせいです。
この RUBY_VM_CHECK_INTS は必要なんでしょうか。


Index: thread.c
===================================================================
--- thread.c	(revision 16676)
+++ thread.c	(working copy)
@@ -197,19 +197,11 @@
 set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
 		     rb_unblock_function_t **oldfunc, void **oldarg)
 {
-  check_ints:
-    RUBY_VM_CHECK_INTS(); /* check signal or so */
     native_mutex_lock(&th->interrupt_lock);
-    if (th->interrupt_flag) {
-	native_mutex_unlock(&th->interrupt_lock);
-	goto check_ints;
-    }
-    else {
-	if (oldfunc) *oldfunc = th->unblock_function;
-	if (oldarg) *oldarg = th->unblock_function_arg;
-	th->unblock_function = func;
-	th->unblock_function_arg = arg;
-    }
+    if (oldfunc) *oldfunc = th->unblock_function;
+    if (oldarg) *oldarg = th->unblock_function_arg;
+    th->unblock_function = func;
+    th->unblock_function_arg = arg;
     native_mutex_unlock(&th->interrupt_lock);
 }


-- 
Yusuke ENDOH <mame@tsg.ne.jp>

In This Thread

Prev Next