e$B1sF#$G$9!#e(B
e$B0J2<$N$h$&$K$9$k$H%O%s%0$9$k$3$H$,$"$j$^$9!#e(B
$ ./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
e$BN.$l$O$3$s$J46$8$G$9!#e(B
-
(1) e$B$G%9%l%C%Ie(B t e$B$Ne(B unblock_function e$B$,e(B
lock_interrupt e$B$Ke(B
e$B$J$j!"e(Bmutex e$B$N2rJ|BT$A$KF~$k!#e(B -
(2) e$B$G%9%l%C%Ie(B t e$B$Ne(B unblock_function (= lock_interrupt)
e$B$,e(B
e$B8F$P$l$k!#e(B -
e$B%9%l%C%Ie(B t e$B$Ne(B unblock_function
e$B$O%/%j%"$5$l$k$Y$-$@$,!“e(B
e$B%/%j%”$5$l$J$$$^$^%9%l%C%Ie(B t e$B$N<B9T$Oe(B (3) e$B$K0$k!#e(B -
(4) e$B$Ge(B mutex e$B$re(B free e$B$9$ke(B (e$B$?$@$74D6-0MB8e(B)
e$B!#e(B -
(5) e$B$G%9%l%C%Ie(B t e$B$Ne(B unblock_function (= lock_interrupt)
e$B$,e(B
e$B8F$P$l$k$,!"e(Block_interrupt e$B$NCf$G2rJ|:Q$_$Ne(B mutex
e$B$K?($k!#e(B
e$B<B:]!"e(Bvalgrind e$B$K$+$1$k$H!"e(Block_interrupt e$BFb$Ge(B Invalid
read
e$B$7$F$$$k$N$,$o$+$j$^$9!#e(B
==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 e$B$,%/%j%"$5$l$J$$$N$Oe(B set_unblock_function
e$BFb$Ge(B
RUBY_VM_CHECK_INTS e$B$r$7$F$$$F!"$=$3$+$ie(B longjmp
e$B$9$k$;$$$G$9!#e(B
e$B$3$Ne(B RUBY_VM_CHECK_INTS e$B$OI,MW$J$s$G$7$g$&$+!#e(B
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);
}