Skip to content

Instantly share code, notes, and snippets.

@k-tsj
Last active December 12, 2015 09:49
Show Gist options
  • Save k-tsj/4754297 to your computer and use it in GitHub Desktop.
Save k-tsj/4754297 to your computer and use it in GitHub Desktop.
Bug #7825 調査状況まとめ

r39197に対するパッチ。

diff —git a/vm.c b/vm.c index 36def2c..b646ea7 100644 - a/vm.c + b/vm.c @ -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
  1. 0×0000555555707f52 in rb_thread_mark (ptr=0×555555de4028) at vm.c:1795
  2. 0×0000555555719a2c in cont_mark (ptr=0×555555de3fe0) at cont.c:146
  3. 0×0000555555719d33 in fiber_mark (ptr=0×555555de3fe0) at cont.c:274
  4. 0×00005555555cc354 in gc_mark_children (objspace=0×5555559f5940, ptr=93824997346480) at gc.c:2823
  5. 0×00005555555cc619 in gc_mark_stacked_objects (objspace=0×5555559f5940) at gc.c:2904
  6. 0×00005555555cc793 in gc_marks (objspace=0×5555559f5940) at gc.c:2949
  7. 0×00005555555caee8 in gc_prepare_free_objects (objspace=0×5555559f5940) at gc.c:2069
  8. 0×00005555555c77cb in newobj (klass=93824997496680, flags=5) at gc.c:653
  9. 0×00005555555c78b1 in rb_newobj_of (klass=93824997496680, flags=5) at gc.c:686
  10. 0×000055555569060d in str_alloc (klass=93824997496680) at string.c:376
  11. 0×00005555556906e1 in str_new (klass=93824997496680, ptr=0×7fffffffc76d “4585”, len=4) at string.c:407
  12. 0×00005555556908cc in rb_str_new (ptr=0×7fffffffc76d “4585”, len=4) at string.c:427
  13. 0×0000555555690a14 in rb_str_new_cstr (ptr=0×7fffffffc76d “4585”) at string.c:452
  14. 0×0000555555690a2e in rb_usascii_str_new_cstr (ptr=0×7fffffffc76d “4585”) at string.c:461
  15. 0×0000555555605c84 in rb_fix2str (x=9171, base=10) at numeric.c:2555
  16. 0×0000555555605cfd in fix_to_s (argc=0, argv=0×0, x=9171) at numeric.c:2586
  17. 0×00005555556ee39d in call_cfunc_m1 (func=0×555555605c9a , recv=9171, argc=0, argv=0×0) at vm_insnhelper.c:1294
  18. 0×00005555556ff529 in vm_call0_cfunc_with_frame (th=0×5555559f5590, ci=0×7fffffffca00, argv=0×0) at vm_eval.c:117
  19. 0×00005555556ff81a in vm_call0_cfunc (th=0×5555559f5590, ci=0×7fffffffca00, argv=0×0) at vm_eval.c:134
  20. 0×00005555556ff9ac in vm_call0_body (th=0×5555559f5590, ci=0×7fffffffca00, argv=0×0) at vm_eval.c:172
  21. 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
  22. 0×00005555556fff96 in rb_call0 (recv=9171, mid=3120, argc=0, argv=0×0, scope=CALL_FCALL, self=93824997347800) at vm_eval.c:311
  23. 0×0000555555700955 in rb_call (recv=9171, mid=3120, argc=0, argv=0×0, scope=CALL_FCALL) at vm_eval.c:569
  24. 0×00005555557011b5 in rb_funcall (recv=9171, mid=3120, n=0) at vm_eval.c:778
  25. 0×00005555556927e3 in rb_obj_as_string (obj=9171) at string.c:883
  26. 0×000055555557f3c3 in ary_join_1 (obj=93824997347800, ary=93824997347800, sep=93824997348520, i=4585, result=93824997346360, first=0×7fffffffcd34) at array.c:1876
  27. 0×000055555557f732 in rb_ary_join (ary=93824997347800, sep=93824997348520) at array.c:1914
  28. 0×000055555557f8d3 in rb_ary_join_m (argc=1, argv=0×7ffff6a09058, ary=93824997347800) at array.c:1950
  29. 0×00005555556ee39d in call_cfunc_m1 (func=0×55555557f874 , recv=93824997347800, argc=1, argv=0×7ffff6a09058) at vm_insnhelper.c:1294
  30. 0×00005555556ef110 in vm_call_cfunc_with_frame (th=0×5555559f5590, reg_cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1438
  31. 0×00005555556ef3dc in vm_call_cfunc (th=0×5555559f5590, reg_cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1528
  32. 0×00005555556f0181 in vm_call_method (th=0×5555559f5590, cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1702
  33. 0×00005555556f092b in vm_call_general (th=0×5555559f5590, reg_cfp=0×7ffff6b08f70, ci=0×555555ded120) at vm_insnhelper.c:1851
  34. 0×00005555556f5dad in vm_exec_core (th=0×5555559f5590, initial=0) at insns.def:1017
  35. 0×0000555555706129 in vm_exec (th=0×5555559f5590) at vm.c:1184
  36. 0×0000555555707194 in rb_iseq_eval_main (iseqval=93825001197440) at vm.c:1433
  37. 0×00005555555b31db in ruby_exec_internal (n=0×555555de0f80) at eval.c:250
  38. 0×00005555555b32ee in ruby_exec_node (n=0×555555de0f80) at eval.c:315
  39. 0×00005555555b32c1 in ruby_run_node (n=0×555555de0f80) at eval.c:307
  40. 0×0000555555574fb9 in main (argc=2, argv=0×7fffffffe038) at main.c:36
1795 rb_gc_mark(ep1); /* envval */ (gdb) p ep $1 = (VALUE *) 0×8 (gdb) p rb_vmdebug_stack_dump_raw(th, th→cfp) - Control frame information -——————————————————————- c:0006 (0×7ffff6b08e30) p:—— s:0018 e:000017 b:——— CFUNC :initialize 0015 (0×7ffff6a09088): 7ffff6b08ef3 0016 (0×7ffff6a09090): 00000008 0017 (0×7ffff6a09098): 7ffff6b08ef3 <- ep - prev ep(s) - ep: 0×7ffff6a09098 c:0005 (0×7ffff6b08e80) p:—— s:0015 e:000014 b:000015 IFUNC 0014 (0×7ffff6a09080): 7ffff6a09061 (= 10) <- ep - prev ep(s) - ep: 0×7ffff6a09080 ep: 0×7ffff6a09060 ep: 0×8 c:0004 (0×7ffff6b08ed0) p:—— s:0014 e:000013 b:——— CFUNC :to_s 0012 (0×7ffff6a09070): 00000008 0013 (0×7ffff6a09078): 00000003 <- ep - prev ep(s) - ep: 0×7ffff6a09078 c:0003 (0×7ffff6b08f20) p:—— s:0012 e:000011 b:——— CFUNC :join 0008 (0×7ffff6a09050): 555555a351d8 ((T_ARRAY)0×555555a351d8) 0009 (0×7ffff6a09058): 555555a354a8 0010 (0×7ffff6a09060): 00000008 0011 (0×7ffff6a09068): 00000003 <- ep - prev ep(s) - ep: 0×7ffff6a09068 c:0002 (0×7ffff6b08f70) p:0018 s:0008 E:002008 b:000008 EVAL t.rb:9 [FINISH] 0002 (0×7ffff6a09020): 00000008 0003 (0×7ffff6a09028): 00000008 0004 (0×7ffff6a09030): 00000008 0005 (0×7ffff6a09038): 00000008 0006 (0×7ffff6a09040): 00000008 0007 (0×7ffff6a09048): 555555a34f30 - prev ep(s) - ep: 0×555555ddeb68 ep: 0×555555b26a88 c:0001 (0×7ffff6b08fc0) p:0000 s:0002 E:001bf8 b:-08224 TOP [FINISH] 0000 (0×7ffff6a09010): 00000008 0001 (0×7ffff6a09018): 555555a47950 - prev ep(s) - ep: 0×555555b26a88

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) - Control frame information -——————————————————————- c:0004 (0×7ffff6b08ed0) p:—— s:0014 e:000013 b:——— CFUNC :to_s 0012 (0×7ffff6a09070): 00000008 0013 (0×7ffff6a09078): 00000003 <- ep - prev ep(s) - ep: 0×7ffff6a09078 c:0003 (0×7ffff6b08f20) p:—— s:0012 e:000011 b:——— CFUNC :join 0008 (0×7ffff6a09050): 555555a351d8 ((T_ARRAY)0×555555a351d8) 0009 (0×7ffff6a09058): 555555a354a8 0010 (0×7ffff6a09060): 00000008 0011 (0×7ffff6a09068): 00000003 <- ep - prev ep(s) - ep: 0×7ffff6a09068 c:0002 (0×7ffff6b08f70) p:0018 s:0008 E:002008 b:000008 EVAL t.rb:9 [FINISH] 0002 (0×7ffff6a09020): 00000008 0003 (0×7ffff6a09028): 00000008 0004 (0×7ffff6a09030): 00000008 0005 (0×7ffff6a09038): 00000008 0006 (0×7ffff6a09040): 00000008 0007 (0×7ffff6a09048): 555555a34f30 - prev ep(s) - ep: 0×555555ddeb68 ep: 0×555555b26a88 c:0001 (0×7ffff6b08fc0) p:0000 s:0002 E:001bf8 b:-08224 TOP [FINISH] 0000 (0×7ffff6a09010): 00000008 0001 (0×7ffff6a09018): 555555a47950 - prev ep(s) - ep: 0×555555b26a88

root_fiber.saved_threadのcfpが古いのが原因?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment