■ delegate.rb どうしてこれが動かないのかと思ったら…… require 'delegate' class A end class B < DelegateClass(A) def initialize super A.new end end class C < B def m puts "C, OK" end end C.new.funcall(:m) # NoMethodError??? funcall を delegate.rb がフックしてて、 勝手に NoMethodError にしてくれてました。 ついでに inspect までデレゲートしてくれたおかげでデバッグしにくいのなんのって。 Rails の奥底でこれにはまったおかげで 4 時間もかかったよ。 知らねーうちにレシーバがすりかわってる (ように見える) んだもんな。 しかもデレゲート先と引数が偶然同じだったがために余計なところをえんえんひきずりまわされてさ。 この仕様はつくづく許しがたい。 (07:48)

■ Rails on YARV YARV で Rails。 なんとか最初の自動生成は通った (通した) んだが、 WEBrick を起動した瞬間に落ちた。 このさい WEBrick をあきらめて CGI でなんとかするほうが早いかな。 さて Rails で CGI はどーすんのかなー。 (08:04)

■ Rails on YARV (2) public/dispatch.cgi という怪しげなファイルを発見！ /var/www/rails/testsite % ./public/dispatch.cgi aamine@serenade DBG> : "/usr/local/pkg/yarv/lib/ruby/gems/1.9/gems/actionpack-1.11.2/lib/action_controller/code_generation.rb:159:in `finish'" DBG> : "/usr/local/pkg/yarv/lib/ruby/gems/1.9/gems/actionpack-1.11.2/lib/action_controller/code_generation.rb:137:in `go'" DBG> : "/usr/local/pkg/yarv/lib/ruby/gems/1.9/gems/actionpack-1.11.2/lib/action_controller/code_generation.rb:132:in `continue'" ……略…… c:0005 p:-001 s:0007 b:0007 l:0006 d:0006 FINISH i:- s: - c:0004 p:-001 s:0006 b:0006 l:0005 d:0005 CFUNC i:require s: - c:0003 p:0037 s:0003 b:0003 l:-861 d:-861 TOP i:<main> s: - c:0002 p:-001 s:0001 b:0001 l:0000 d:0000 FINISH i:- s: - c:0001 p:-001 s:0000 b:-001 l:0000 d:0000 ------ i:- s: - --------------------------- [BUG] Segmentation fault ruby 1.9.0 (2006-02-14) [x86_64-linux] そんなお約束なー！ (08:08)

■ Rails on YARV (3) 問題の個所を切り出しただけでは再現しない。 嫌だなあ。つくづく嫌だなあ。 (08:18)

■ Rails on YARV (4) わかったよー、追うよ追いますよ！ /var/www/rails/testsite % gdb -c core /usr/local/pkg/yarv/bin/ruby ずばっと略 (gdb) bt #0 0x0000002a95d8fdd0 in raise () from /lib/libc.so.6 #1 0x0000002a95d91280 in abort () from /lib/libc.so.6 #2 0x0000002a9569d1b5 in rb_bug (fmt=0x2a9573d021 "Segmentation fault") at error.c:171 #3 0x0000002a956f7ae0 in sigsegv (sig=11) at signal.c:467 #4 <signal handler called> #5 th_invoke_proc (th=0x55d1d0, proc=0x11a7d80, self=0, argc=1, argv=0x2a96102550) at vm.c:666 #6 0x0000002a9571e984 in proc_call (argc=1, argv=0x2a96102550, procval=182929376352) at yarv.h:49 #7 0x0000002a9571c3bb in call_cfunc (func=0x2a9571e940 <proc_call>, recv=182929376352, len=0, argc=5624272, argv=0x0) at call_cfunc.h:24 #8 0x0000002a9571a445 in th_eval (th=0x55d1d0, initial=0) at insns.def:1253 #9 0x0000002a9571c02d in th_eval_body (th=0x55d1d0) at vm.c:1449 #10 0x0000002a95717897 in th_call0 (th=0x55d1d0, klass=0, recv=182929388432, id=182902709320, oid=182906266960, argc=2, argv=0x2a96102468, body=0xc4d580, nosuper=0) at vm.c:425 #11 0x0000002a956a507e in rb_call (klass=182916132936, recv=182929388432, mid=3977, argc=2, argv=0x2a96102438, scope=1) at yarv.h:49 #12 0x0000002a9571a5b0 in th_eval (th=0x55d1d0, initial=0) at vm.c:1149 #13 0x0000002a9571c02d in th_eval_body (th=0x55d1d0) at vm.c:1449 #14 0x0000002a95717897 in th_call0 (th=0x55d1d0, klass=0, recv=182929400152, id=182902709320, oid=182906266960, argc=2, argv=0x2a961022f8, body=0xc4d580, nosuper=0) at vm.c:425 #15 0x0000002a956a507e in rb_call (klass=182916132936, recv=182929400152, mid=3977, argc=2, argv=0x2a961022c8, scope=1) at yarv.h:49 #16 0x0000002a9571a5b0 in th_eval (th=0x55d1d0, initial=0) at vm.c:1149 #17 0x0000002a9571c02d in th_eval_body (th=0x55d1d0) at vm.c:1449 #18 0x0000002a95717df6 in th_invoke_yield (th=0x55d1d0, argc=1, argv=0xfaffff21) at vm.c:640 #19 0x0000002a956a40b6 in rb_yield_0 (val=182929495112, self=0, klass=0, flags=-1780884408, avalue=-1777326768) at yarv.h:49 #20 0x0000002a9568fbe0 in rb_ary_each (ary=182929495392) at array.c:1147 #21 0x0000002a9571c3c4 in call_cfunc (func=0x2a9568fb70 <rb_ary_each>, recv=182929495392, len=0, argc=5624272, argv=0x0) at call_cfunc.h:27 #22 0x0000002a9571a445 in th_eval (th=0x55d1d0, initial=0) at insns.def:1253 #23 0x0000002a9571c02d in th_eval_body (th=0x55d1d0) at vm.c:1449 #24 0x0000002a95717897 in th_call0 (th=0x55d1d0, klass=0, recv=182929403472, id=182902709320, oid=182906266960, argc=2, argv=0x2a961021c0, body=0xc4d580, nosuper=0) at vm.c:425 #25 0x0000002a956a507e in rb_call (klass=182916132936, recv=182929403472, mid=3977, argc=2, argv=0x2a96102190, scope=1) at yarv.h:49 以下略 とりあえず一番上のフレームを見てみる。 (gdb) f 6 #6 0x0000002a9571e984 in proc_call (argc=1, argv=0x2a96102550, procval=182929376352) at yarv.h:49 49 { (gdb) list 44 return theYarvVM; 45 } 46 47 static inline yarv_thread_t * 48 yarv_get_current_running_thread(void) 49 { 50 return yarvCurrentThread; 51 } 52 53 static inline void (gdb) p yarvCurrentThread $1 = (yarv_thread_t *) 0x55d1d0 (gdb) p *$1 $2 = {self = 182906065688, vm = 0x55d0a0, stack = 0x2a96102010, stack_size = 131072, cfp = 0x2a96200e90, safe_level = 0, state = 0, passed_block = 0x0, top_local_tbl = 0x0, base_block = 0x0, local_lfp = 0x0, local_svar = 0, thread_id = 182904806112, status = THREAD_RUNNABLE, priority = 0, native_thread_data = {dummy = 0}, thgroup = 182906060288, value = 0, wait_thread_value = 0, errinfo = 4, throwed_errinfo = 0, interrupt_flag = 0, tag = 0x7fbfffae00, parse_in_eval = 0, local_storage = 0xe8a8c0, signal_queue = {buff = {0 <repeats 16 times>}, head = 0, tail = 0}, signal_thread_list = 0x0, first_proc = 0, first_args = 0, machine_stack_start = 0x7fbffff600, machine_stack_end = 0x7fbfffc560, machine_regs = {{__jmpbuf = {5624568, 5624272, 5624272, 4, 182897364680, 1, 548682057072, 182895908384}, __mask_was_saved = 0, __saved_mask = {__val = {0 <repeats 16 times>}}}}, stat_insn_usage = 0, method_missing_reason = 0, abort_on_exception = 0} GET_THREAD() の中に入っちゃってるな。 これは意味なさそう。 proc_call() の引数を見たほうがいいか。 (gdb) p 0x2a96102550 $3 = 182906266960 (gdb) p (VALUE*)$3 $4 = (long unsigned int *) 0x2a96102550 (gdb) p *$4 $5 = 182929375032 (gdb) rp $5 T_STRING $6 = {basic = {flags = 7, klass = 182906235808}, len = 54, ptr = 0x12eb390 "{\"controller\" => controller_value, \"action\" => \"wsdl\"}", aux = {capa = 62, shared = 62}} (gdb) rp 182929376352 T_DATA $7 = {basic = {flags = 18, klass = 182906068888}, dmark = 0x2a9571e860 <proc_mark>, dfree = 0x2a9571e840 <proc_free>, data = 0x11a7d80} (gdb) p $7.data $8 = (void *) 0x11a7d80 (gdb) p (yarv_proc_t*)$8 $9 = (struct {...} *) 0x11a7d80 (gdb) p *$9 $10 = {block = {self = 0, lfp = 0x0, dfp = 0x0, iseq = 0x0, proc = 0}, envval = 0, blockprocval = 0, safe_level = 0, is_lambda = 0, special_cref_stack = 0x0} 呼ぼうとした Proc の実体が初期化されてないのか……？ (08:30)

■ Rails on YARV (5) おーし、 require 'rubygems' require_gem 'actionpack' ActionController::Routing::Routes.draw do |map| map.connect ':controller/service.wsdl', :action => 'wsdl' map.connect ':controller/:action/:id' end で再現。あとはどこまで短縮できるかだ。 (09:01)

■ Rails on YARV (6) 特定完了 ~/c/yarv/REPOS/actionpack % /usr/local/pkg/yarv/bin/ruby -e 'Proc.new{}.dup.call' DBG> : "-e:1:in `<main>'" -- stack frame ------------ 0x2a96102010 (0000): 00000001 0x2a96102018 (0001): 00000004 0x2a96102020 (0002): 2a960cf298 0x2a96102028 (0003): 2a960cf248 0x2a96102030 (0004): 00000001 <- lfp <- dfp -- control frame ---------- c:0004 p:-001 s:0005 b:0005 l:0004 d:0004 CFUNC i:call s: - c:0003 p:0025 s:0003 b:0003 l:-815 d:-815 TOP i:<main> s: c:0002 p:-001 s:0001 b:0001 l:0000 d:0000 FINISH i:- s: - c:0001 p:-001 s:0000 b:-001 l:0000 d:0000 ------ i:- s: - --------------------------- [BUG] Segmentation fault ruby 1.9.0 (2006-02-14) [x86_64-linux] zsh: 24815 abort (core dumped) /usr/local/pkg/yarv/bin/ruby -e 'Proc.new{}.dup.call' (09:53)

■ Rails on YARV (8) むっ？！ よく見たら WEBrick のときの SEGV も同じじゃないか。 ということはこのバグが直れば WEBrick で動くのかも。 (09:57)

■ Rails on YARV (9) そうか……ということはこれでも落ちるだろうなあ。 ~/c/yarv % ./ruby -e 'Proc.allocate.call' DBG> : "-e:1:in `<main>'" -- stack frame ------------ 0x2a96102010 (0000): 00000001 0x2a96102018 (0001): 00000004 0x2a96102020 (0002): 2a960cf4a0 0x2a96102028 (0003): 2a960cf478 0x2a96102030 (0004): 00000001 <- lfp <- dfp -- control frame ---------- c:0004 p:-001 s:0005 b:0005 l:0004 d:0004 CFUNC i:call s: - c:0003 p:0019 s:0003 b:0003 l:-811 d:-811 TOP i:<main> s: - c:0002 p:-001 s:0001 b:0001 l:0000 d:0000 FINISH i:- s: - c:0001 p:-001 s:0000 b:-001 l:0000 d:0000 ------ i:- s: - --------------------------- [BUG] Segmentation fault ruby 1.9.0 (2006-02-14) [x86_64-linux] zsh: 24828 abort (core dumped) ./ruby -e 'Proc.allocate.call' やはり。ということは、こんなのとか、 ~/c/yarv % ./ruby -e 'p YARVCore::InstructionSequence.allocate' DBG> : "-e:1:in `p'" DBG> : "-e:1:in `<main>'" -- stack frame ------------ 0x2a95ee2010 (0000): 00000001 0x2a95ee2018 (0001): 00000004 0x2a95ee2020 (0002): 2a95eaf450 0x2a95ee2028 (0003): 2a95ede408 0x2a95ee2030 (0004): 2a95eaf428 0x2a95ee2038 (0005): 00000001 0x2a95ee2040 (0006): 00000001 <- lfp <- dfp -- control frame ---------- c:0005 p:-001 s:0007 b:0007 l:0006 d:0006 CFUNC i:inspect s: - c:0004 p:-001 s:0006 b:0006 l:0005 d:0005 CFUNC i:p s: - c:0003 p:0022 s:0003 b:0003 l:-093 d:-093 TOP i:<main> s: - c:0002 p:-001 s:0001 b:0001 l:0000 d:0000 FINISH i:- s: - c:0001 p:-001 s:0000 b:-001 l:0000 d:0000 ------ i:- s: - --------------------------- [BUG] Segmentation fault ruby 1.9.0 (2006-02-14) [x86_64-linux] こんなのとか、 ~/c/yarv % ./ruby -e 'p YARVCore::VM.allocate.eval(YARVCore::InstructionSequence.allocate)' DBG> : "-e:1:in `eval'" DBG> : "-e:1:in `<main>'" -- stack frame ------------ 0x2a95ee2010 (0000): 00000001 0x2a95ee2018 (0001): 00000004 0x2a95ee2020 (0002): 2a95eaf2e8 0x2a95ee2028 (0003): 2a95ede408 0x2a95ee2030 (0004): 2a95eaf2c0 0x2a95ee2038 (0005): 2a95eaf298 0x2a95ee2040 (0006): 00000001 0x2a95ee2048 (0007): 00000001 0x2a95ee2050 (0008): 00000001 <- lfp <- dfp -- control frame ---------- c:0006 p:-001 s:0009 b:0009 l:0008 d:0008 TOP i:(null) s: - c:0005 p:-001 s:0008 b:0008 l:0007 d:0007 FINISH i:- s: - c:0004 p:-001 s:0007 b:0007 l:0006 d:0006 CFUNC i:eval s: - c:0003 p:0037 s:0004 b:0003 l:-083 d:-083 TOP i:<main> s: - c:0002 p:-001 s:0001 b:0001 l:0000 d:0000 FINISH i:- s: - c:0001 p:-001 s:0000 b:-001 l:0000 d:0000 ------ i:- s: - --------------------------- [BUG] Segmentation fault ruby 1.9.0 (2006-02-14) [x86_64-linux] こんなのもヤバげということに…… ~/c/yarv % ./ruby -e 'p eval("", YARVCore::VM::Binding.allocate)' -e:1:in `eval': -e:1:in `eval': wrong argument type false (expected Data) (TypeError) from -e:1:in `<main>' ~/c/yarv % ./ruby -e 'eval("", binding().dup)' -e:1:in `eval': -e:1:in `eval': wrong argument type false (expected Data) (TypeError) from -e:1:in `<main>' (10:23)