r39197に対するパッチ。
diff —git a/vm.c b/vm.c index 36def2c..b646ea7 100644@ -262,7 +262,7 @
ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
*/
#define ENV_IN_HEAP_P(th, env) \
- (!((th)→stack < (env) && (env) < ((th)→stack + (th)→stack_size)))
+ (!((th)→stack <= (env) && (env) < ((th)→stack + (th)→stack_size)))
#define ENV_VAL(env) ((env)1)
static void
@ -1775,10 +1775,21 @
rb_thread_mark(void *ptr)
rb_gc_mark_locations(p, p + th→mark_stack_len);
while (cfp != limit_cfp) {
+ VALUE *ep = cfp→ep;
rb_iseq_t *iseq = cfp→iseq;
rb_gc_mark(cfp→proc);
rb_gc_mark(cfp→self);
rb_gc_mark(cfp→klass);
+ while (1) {
+ if (ENV_IN_HEAP_P(th, ep)) {
+ rb_gc_mark(ep1); /* envval */
+ break;
+ }
+ if (VM_EP_LEP_P(ep)) {
+ break;
+ }
+ ep = VM_EP_PREV_EP(ep);
+ }
if (iseq) {
rb_gc_mark(RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq→self : (VALUE)iseq);
}
再現スクリプト。
1.times { Fiber.new{} } (0…14000).to_a.join(", ")SEGVはroot_fiberのfiber_mark時に起きている。SEGV時のVMの状態は以下の通り。
(gdb) bt- 0×0000555555707f52 in rb_thread_mark (ptr=0×555555de4028) at vm.c:1795
- 0×0000555555719a2c in cont_mark (ptr=0×555555de3fe0) at cont.c:146
- 0×0000555555719d33 in fiber_mark (ptr=0×555555de3fe0) at cont.c:274
- 0×00005555555cc354 in gc_mark_children (objspace=0×5555559f5940, ptr=93824997346480) at gc.c:2823
- 0×00005555555cc619 in gc_mark_stacked_objects (objspace=0×5555559f5940) at gc.c:2904
- 0×00005555555cc793 in gc_marks (objspace=0×5555559f5940) at gc.c:2949
- 0×00005555555caee8 in gc_prepare_free_objects (objspace=0×5555559f5940) at gc.c:2069
- 0×00005555555c77cb in newobj (klass=93824997496680, flags=5) at gc.c:653
- 0×00005555555c78b1 in rb_newobj_of (klass=93824997496680, flags=5) at gc.c:686
- 0×000055555569060d in str_alloc (klass=93824997496680) at string.c:376
- 0×00005555556906e1 in str_new (klass=93824997496680, ptr=0×7fffffffc76d “4585”, len=4) at string.c:407
- 0×00005555556908cc in rb_str_new (ptr=0×7fffffffc76d “4585”, len=4) at string.c:427
- 0×0000555555690a14 in rb_str_new_cstr (ptr=0×7fffffffc76d “4585”) at string.c:452
- 0×0000555555690a2e in rb_usascii_str_new_cstr (ptr=0×7fffffffc76d “4585”) at string.c:461
- 0×0000555555605c84 in rb_fix2str (x=9171, base=10) at numeric.c:2555
- 0×0000555555605cfd in fix_to_s (argc=0, argv=0×0, x=9171) at numeric.c:2586
- 0×00005555556ee39d in call_cfunc_m1 (func=0×555555605c9a , recv=9171, argc=0, argv=0×0) at vm_insnhelper.c:1294
- 0×00005555556ff529 in vm_call0_cfunc_with_frame (th=0×5555559f5590, ci=0×7fffffffca00, argv=0×0) at vm_eval.c:117
- 0×00005555556ff81a in vm_call0_cfunc (th=0×5555559f5590, ci=0×7fffffffca00, argv=0×0) at vm_eval.c:134
- 0×00005555556ff9ac in vm_call0_body (th=0×5555559f5590, ci=0×7fffffffca00, argv=0×0) at vm_eval.c:172
- 0×00005555556ff157 in vm_call0 (th=0×5555559f5590, recv=9171, id=3120, argc=0, argv=0×0, me=0×555555a91190, defined_class=93824997485560) at vm_eval.c:49
- 0×00005555556fff96 in rb_call0 (recv=9171, mid=3120, argc=0, argv=0×0, scope=CALL_FCALL, self=93824997347800) at vm_eval.c:311
- 0×0000555555700955 in rb_call (recv=9171, mid=3120, argc=0, argv=0×0, scope=CALL_FCALL) at vm_eval.c:569
- 0×00005555557011b5 in rb_funcall (recv=9171, mid=3120, n=0) at vm_eval.c:778
- 0×00005555556927e3 in rb_obj_as_string (obj=9171) at string.c:883
- 0×000055555557f3c3 in ary_join_1 (obj=93824997347800, ary=93824997347800, sep=93824997348520, i=4585, result=93824997346360, first=0×7fffffffcd34) at array.c:1876
- 0×000055555557f732 in rb_ary_join (ary=93824997347800, sep=93824997348520) at array.c:1914
- 0×000055555557f8d3 in rb_ary_join_m (argc=1, argv=0×7ffff6a09058, ary=93824997347800) at array.c:1950
- 0×00005555556ee39d in call_cfunc_m1 (func=0×55555557f874 , recv=93824997347800, argc=1, argv=0×7ffff6a09058) at vm_insnhelper.c:1294
- 0×00005555556ef110 in vm_call_cfunc_with_frame (th=0×5555559f5590, reg_cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1438
- 0×00005555556ef3dc in vm_call_cfunc (th=0×5555559f5590, reg_cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1528
- 0×00005555556f0181 in vm_call_method (th=0×5555559f5590, cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1702
- 0×00005555556f092b in vm_call_general (th=0×5555559f5590, reg_cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1851
- 0×00005555556f5dad in vm_exec_core (th=0×5555559f5590, initial=0) at insns.def:1017
- 0×0000555555706129 in vm_exec (th=0×5555559f5590) at vm.c:1184
- 0×0000555555707194 in rb_iseq_eval_main (iseqval=93825001197440) at vm.c:1433
- 0×00005555555b31db in ruby_exec_internal (n=0×555555de0f80) at eval.c:250
- 0×00005555555b32ee in ruby_exec_node (n=0×555555de0f80) at eval.c:315
- 0×00005555555b32c1 in ruby_run_node (n=0×555555de0f80) at eval.c:307
- 0×0000555555574fb9 in main (argc=2, argv=0×7fffffffe038) at main.c:36
c:0005のprev epがおかしいのがSEGVする直接的な原因。
root_fiber→cont.saved_threadとstackを共有しているruby_current_threadの情報は以下の通り。
(gdb) p rb_vmdebug_stack_dump_raw(ruby_current_thread, ruby_current_thread→cfp)root_fiber.saved_threadのcfpが古いのが原因?