cool.io という Ruby C拡張ライブラリをいじっていて SEGV 起こしてしまったので追いたい。
gcc のオプションを -O0 -ggdb3 にしたほうが SEGV 追いやすいとのことなので、Makefile 吐いていじる
$ ruby ext/cool.io/extconf.rb
$ vim Makefile
おまけ:Makefile いじって gcc のオプションに --savetemps を足すと、プリコンパイルを通した結果の .i ファイルが作られる。プリコンパイル結果を追いたい場合捗る。
コア吐かせる準備をしておく。
$ ulimit -c unlimited
プログラム実行して SEGV 発生させる。すると core.{pid} なファイルができているはず。
ruby のパスと core ファイルを指定して gdb を起動し、backtrace を表示する
$ gdb `rbenv which ruby` core.2101
(gdb) bt
#0 0x00d98410 in __kernel_vsyscall ()
#1 0x00138df0 in raise () from /lib/libc.so.6
#2 0x0013a701 in abort () from /lib/libc.so.6
#3 0x006a0877 in rb_bug (fmt=0x6d19b5 "Segmentation fault") at error.c:309
#4 0x005c0e86 in sigsegv (sig=11, info=0x959461c, ctx=0x959469c) at signal.c:672
#5 <signal handler called>
#6 ev_feed_event (loop=0x96a08e0, w=0xb7c0a844, revents=256) at ../../../../ext/cool.io/../libev/ev.c:1702
#7 0x004b0eeb in timers_reify (loop=0x96a08e0, flags=2) at ../../../../ext/cool.io/../libev/ev.c:1725
#8 ev_run (loop=0x96a08e0, flags=2) at ../../../../ext/cool.io/../libev/ev.c:3460
#9 0x004a9d3d in ev_loop (argc=1, argv=0xb7c8d01c, self=154926840) at ../../../../ext/cool.io/../libev/ev.h:826
#10 Coolio_Loop_run_once (argc=1, argv=0xb7c8d01c, self=154926840) at ../../../../ext/cool.io/loop.c:226
#11 0x006269b5 in call_cfunc_m1 (func=0x4a9c50 <Coolio_Loop_run_once>, recv=154926840, argc=1, argv=0xb7c8d01c) at vm_insnhelper.c:1325
#12 0x0062c22c in vm_call_cfunc_with_frame (th=0x96fca08, reg_cfp=0xb7d0cfb8, ci=<value optimized out>) at vm_insnhelper.c:1469
#13 0x0063d40d in vm_exec_core (th=0x96fca08, initial=<value optimized out>) at insns.def:1017
#14 0x00642b27 in vm_exec (th=0x96fca08) at vm.c:1201
#15 0x00643ecb in invoke_block_from_c (th=0x96fca08, proc=0x9645ec8, self=154913200, defined_class=147225780, argc=0, argv=0x93bfc6c, blockptr=0x0) at vm.c:648
#16 vm_invoke_proc (th=0x96fca08, proc=0x9645ec8, self=154913200, defined_class=147225780, argc=0, argv=0x93bfc6c, blockptr=0x0) at vm.c:696
#17 0x00657e33 in thread_start_func_2 (th=0x96fca08, stack_start=<value optimized out>) at thread.c:512
#18 0x0065804e in thread_start_func_1 (th_ptr=0x96fca08) at thread_pthread.c:765
#19 0x0083c852 in start_thread () from /lib/libpthread.so.0
#20 0x001e3a8e in clone () from /lib/libc.so.6
sigsegv がおきた次のフレームに移動して変数の中身などを表示する
(gdb) frame 6
#6 ev_feed_event (loop=0x96a08e0, w=0xb7c0a844, revents=256) at ../../../../ext/cool.io/../libev/ev.c:1702
1702 pendings [pri][w_->pending - 1].events |= revents;
(gdb) p w
$1 = (void *) 0xb7c0a844
(gdb) p pendings
$2 = {0x0, 0x0, 0x9687ed8, 0x0, 0x0}
(gdb) p pri
$3 = 6832926
(gdb) p w_->pending
Cannot access memory at address 0x4
0x4 は ruby の nil らしいので、そこがおかしい
ToDo: watchpoint 張って追いかける