Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

There and Back Again

  1. There and Back Again – or – How I Set out to Benchmark an Algorithm and Ended Up Fixing Ruby
  2. About Me Name: Joshua Ballanco
  3. About Me Location: Ankara, Turkey
  4. About Me Employer:
  5. About Me Employer: Burnside Digital
  6. WARNING This is an ADVANCED presentation. While you do not need to be an expert on the inner workings of C Ruby, this talk does presume you are familiar with concepts such as pointers, memory allocation, and pages (no, not book pages, memory pages). If you are prone to motion sickness or become nauseous at the sight of hexadecimal memory addresses, this talk may not be for you.
  7. Prelude: How can I contribute to Ruby?
  8. Prelude: How can I contribute to Ruby? Use It!
  9. 4 Rs of Bug Reporting • Reproduce • Report • Reduce • Regress
  10. Reproduce It! • Can you make the bug occur every time? most of the time? some of the time? • .irbrc, .gemrc, Other rc files • Environment and Environment Variables • rvm/rbenv • Ask a friend
  11. Report It! • Ruby Bug Tracker: http://bugs.ruby-lang.org/ • All steps to reproduce, bonus points for attachments • Ruby Version • Crash log (hint: look in Console.app)
  12. Reduce It! • Eliminate libraries • Simple scripts are best • Shrink code (5 or fewer lines is ideal)
  13. Regress It! • Try different Ruby versions • Better: try different Ruby releases • Best: git bisect! • Bonus: try different build settings
  14. 5 Rs of Bug Reporting • Reproduce • Report • Reduce • Regress • Repair!
  15. A long time ago in a faraway land...
  16. A long time ago in a faraway land...
  17. A long time ago in a faraway land...
  18. A long time ago in a faraway land...
  19. A long time ago in a faraway land...
  20. A long time ago in a faraway land... for full backstory, see: http://blogs.burnsidedigital.com/
  21. Disaster Strikes! > ruby delegation_bench.rb Call one method user system total real Pre-delegate 4.940000 0.020000 4.960000 ( 4.954945) Post-delegate 0.060000 0.000000 0.060000 ( 0.060528) On Demand 0.010000 0.000000 0.010000 ( 0.010604) Reversible 0.110000 0.000000 0.110000 ( 0.101494) Call one method 100 times ... Call three methods 100 times user system total real Pre-delegate 5.640000 0.000000 5.640000 ( 5.640255) Post-delegate 0.980000 0.000000 0.980000 ( 0.975919) On Demand 1.210000 0.000000 1.210000 ( 1.205214) Reversible 1.020000 0.000000 1.020000 ( 1.027759) Call three methods 10,000 times user system total real Pre-delegate ruby(5919,0x7fff732a5180) malloc: *** error for object 0x7fb18f80d750: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug zsh: abort ruby delegation_bench.rb
  22. Disaster Strikes!
  23. Pack Your Bags • Download Ruby Source (https://github.com/ruby/ruby) • Build ./configure && make (see ./configure --help for more)
  24. Study the Map • ./include/ruby/ruby.h • ID => symbols • VALUE => everything else • rb_id2name => dump symbols in GDB • rb_string_value_cstr => #to_s for GDB • vm_call_method
  25. Bring Your Gardener miniruby • like ruby, only smaller • lexer, parser, interpreter,VM/runtime • core library classes • make miniruby to build
  26. Weapon of Choice gdb • gdb ./miniruby • Set pre-run breakpoints • Pass arguments to miniruby with “run” • Watch it crash!
  27. > gdb ./miniruby ... (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001100397198 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  28. > gdb ./miniruby ... (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001100397198 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  29. > gdb ./miniruby ... (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001100397198 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  30. (gdb) bt #0 0x00007fff8e611cfb in tiny_free_list_remove_ptr () #1 0x00007fff8e60e76d in szone_free_definite_size () #2 0x00007fff8e608898 in free () #3 0x000000010012f5dc in rb_free_method_entry [inlined] () at vm_method.c:155 #4 0x000000010012f5dc in rb_sweep_method_entry (pvm=0xb592caed) at... #5 0x000000010004a00a in gc_lazy_sweep [inlined] () at gc.c:2107 #6 0x000000010004a00a in rb_newobj () at gc.c:1183 #7 0x000000010000caf4 in ary_alloc [inlined] () at array.c:301 #8 0x000000010000caf4 in ary_new (klass=4303833400, capa=3046355020) at... #9 0x000000010000d165 in rb_ary_new2 [inlined] () at array.c:334 #10 0x000000010000d165 in rb_ary_new4 (n=0, elts=0x7fff5fbfee90) at array.c... #11 0x000000010013288a in vm_yield_with_cfunc (th=0x100303e90, block=... #12 0x000000010013dbb1 in rb_vm_invoke_proc (th=0x100303e90, proc=... #13 0x000000010013bd90 in vm_call_bmethod [inlined] () at vm_insnhelper.c:433 #14 0x000000010013bd90 in vm_call_method (th=0x7fff5fbfef60, cfp=0x7fff5fbfef60, num=8766224, blockptr=0x7fff5fbfef60, flag=140734799802208, id=4298129040, me=0x10038ec90, recv=4303733520) at vm_insnhelper.c:566 ... (gdb) p rb_string_value_cstr(4303733520)
  31. (gdb) bt #0 0x00007fff8e611cfb in tiny_free_list_remove_ptr () #1 0x00007fff8e60e76d in szone_free_definite_size () #2 0x00007fff8e608898 in free () #3 0x000000010012f5dc in rb_free_method_entry [inlined] () at vm_method.c:155 #4 0x000000010012f5dc in rb_sweep_method_entry (pvm=0xb592caed) at... #5 0x000000010004a00a in gc_lazy_sweep [inlined] () at gc.c:2107 #6 0x000000010004a00a in rb_newobj () at gc.c:1183 #7 0x000000010000caf4 in ary_alloc [inlined] () at array.c:301 #8 0x000000010000caf4 in ary_new (klass=4303833400, capa=3046355020) at... #9 0x000000010000d165 in rb_ary_new2 [inlined] () at array.c:334 #10 0x000000010000d165 in rb_ary_new4 (n=0, elts=0x7fff5fbfee90) at array.c... #11 0x000000010013288a in vm_yield_with_cfunc (th=0x100303e90, block=... #12 0x000000010013dbb1 in rb_vm_invoke_proc (th=0x100303e90, proc=... #13 0x000000010013bd90 in vm_call_bmethod [inlined] () at vm_insnhelper.c:433 #14 0x000000010013bd90 in vm_call_method (th=0x7fff5fbfef60, cfp=0x7fff5fbfef60, num=8766224, blockptr=0x7fff5fbfef60, flag=140734799802208, id=4298129040, me=0x10038ec90, recv=4303733520) at vm_insnhelper.c:566 ... (gdb) p rb_string_value_cstr(4303733520)
  32. (gdb) bt #0 0x00007fff8e611cfb in tiny_free_list_remove_ptr () #1 0x00007fff8e60e76d in szone_free_definite_size () #2 0x00007fff8e608898 in free () #3 0x000000010012f5dc in rb_free_method_entry [inlined] () at vm_method.c:155 #4 0x000000010012f5dc in rb_sweep_method_entry (pvm=0xb592caed) at... #5 0x000000010004a00a in gc_lazy_sweep [inlined] () at gc.c:2107 #6 0x000000010004a00a in rb_newobj () at gc.c:1183 #7 0x000000010000caf4 in ary_alloc [inlined] () at array.c:301 #8 0x000000010000caf4 in ary_new (klass=4303833400, capa=3046355020) at... #9 0x000000010000d165 in rb_ary_new2 [inlined] () at array.c:334 #10 0x000000010000d165 in rb_ary_new4 (n=0, elts=0x7fff5fbfee90) at array.c... #11 0x000000010013288a in vm_yield_with_cfunc (th=0x100303e90, block=... #12 0x000000010013dbb1 in rb_vm_invoke_proc (th=0x100303e90, proc=... #13 0x000000010013bd90 in vm_call_bmethod [inlined] () at vm_insnhelper.c:433 #14 0x000000010013bd90 in vm_call_method (th=0x7fff5fbfef60, cfp=0x7fff5fbfef60, num=8766224, blockptr=0x7fff5fbfef60, flag=140734799802208, id=4298129040, me=0x10038ec90, recv=4303733520) at vm_insnhelper.c:566 ... (gdb) p rb_string_value_cstr(4303733520)
  33. (gdb) p rb_string_value_cstr(4303733520) ./bug.rb:7: [BUG] object allocation during garbage collection phase ruby 1.9.3p286 (2012-10-12 revision 36243) [x86_64-darwin12.2.0] -- Control frame information ----------------------------------------------- c:0009 p:0011 s:0021 b:0021 l:000888 d:000020 BLOCK ./bug.rb:7 c:0008 p:---- s:0019 b:0019 l:000018 d:000018 FINISH c:0007 p:---- s:0017 b:0017 l:000016 d:000016 CFUNC :times ...
  34. (gdb) p rb_string_value_cstr(4303733520) ./bug.rb:7: [BUG] object allocation during garbage collection phase ruby 1.9.3p286 (2012-10-12 revision 36243) [x86_64-darwin12.2.0] -- Control frame information ----------------------------------------------- c:0009 p:0011 s:0021 b:0021 l:000888 d:000020 BLOCK ./bug.rb:7 c:0008 p:---- s:0019 b:0019 l:000018 d:000018 FINISH c:0007 p:---- s:0017 b:0017 l:000016 d:000016 CFUNC :times ...
  35. (gdb) bt #0 0x00007fff8e611cfb in tiny_free_list_remove_ptr () #1 0x00007fff8e60e76d in szone_free_definite_size () #2 0x00007fff8e608898 in free () #3 0x000000010012f5dc in rb_free_method_entry [inlined] () at vm_method.c:155 #4 0x000000010012f5dc in rb_sweep_method_entry (pvm=0xb592caed) at... #5 0x000000010004a00a in gc_lazy_sweep [inlined] () at gc.c:2107 #6 0x000000010004a00a in rb_newobj () at gc.c:1183 #7 0x000000010000caf4 in ary_alloc [inlined] () at array.c:301 #8 0x000000010000caf4 in ary_new (klass=4303833400, capa=3046355020) at... #9 0x000000010000d165 in rb_ary_new2 [inlined] () at array.c:334 #10 0x000000010000d165 in rb_ary_new4 (n=0, elts=0x7fff5fbfee90) at array.c... #11 0x000000010013288a in vm_yield_with_cfunc (th=0x100303e90, block=... #12 0x000000010013dbb1 in rb_vm_invoke_proc (th=0x100303e90, proc=... #13 0x000000010013bd90 in vm_call_bmethod [inlined] () at vm_insnhelper.c:433 #14 0x000000010013bd90 in vm_call_method (th=0x7fff5fbfef60, cfp=0x7fff5fbfef60, num=8766224, blockptr=0x7fff5fbfef60, flag=140734799802208, id=4298129040, me=0x10038ec90, recv=4303733520) at vm_insnhelper.c:566 ...
  36. Call three methods 10,000 times user system total real Pre-delegate ruby(5919,0x7fff732a5180) malloc: *** error for object 0x7fb18f80d750: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug
  37. > gdb ./miniruby ... (gdb) break malloc_error_break Function "malloc_error_break" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (malloc_error_break) pending. (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Breakpoint 1 at 0x7fff8e607558 Pending breakpoint 1 - "malloc_error_break" resolved Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x000000110060c908 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  38. > gdb ./miniruby ... (gdb) break malloc_error_break Function "malloc_error_break" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (malloc_error_break) pending. (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Breakpoint 1 at 0x7fff8e607558 Pending breakpoint 1 - "malloc_error_break" resolved Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x000000110060c908 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  39. > gdb ./miniruby ... (gdb) break malloc_error_break Function "malloc_error_break" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (malloc_error_break) pending. (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Breakpoint 1 at 0x7fff8e607558 Pending breakpoint 1 - "malloc_error_break" resolved Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x000000110060c908 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  40. > gdb ./miniruby ... (gdb) break malloc_error_break Function "malloc_error_break" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (malloc_error_break) pending. (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb Reading symbols for shared libraries ++............................ done Breakpoint 1 at 0x7fff8e607558 Pending breakpoint 1 - "malloc_error_break" resolved Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x000000110060c908 0x00007fff8e611cfb in tiny_free_list_remove_ptr () (gdb)
  41. Advanced Weaponry MallocStackLoggingNoCompact • man malloc • Set environment variables to log the stack during allocations • Run in GDB, use malloc_history to view stacks • CFLAGS=”-O0 -g” ./configure
  42. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb zsh(49630) malloc: recording malloc stacks to disk using standard recorder zsh(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly ... Reading symbols for shared libraries ++............................ done miniruby(49630) malloc: recording malloc stacks to disk using standard recorder miniruby(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly miniruby(49630) malloc: stack logs deleted from /tmp/stack-logs.49630.arch. 2JF4tB.index miniruby(49630) malloc: stack logs being written into /tmp/stack-logs. 49630.miniruby.lZtwm8.index Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001000000008 0x00007fff8e611cfb in tiny_free_list_remove_ptr ()
  43. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb zsh(49630) malloc: recording malloc stacks to disk using standard recorder zsh(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly ... Reading symbols for shared libraries ++............................ done miniruby(49630) malloc: recording malloc stacks to disk using standard recorder miniruby(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly miniruby(49630) malloc: stack logs deleted from /tmp/stack-logs.49630.arch. 2JF4tB.index miniruby(49630) malloc: stack logs being written into /tmp/stack-logs. 49630.miniruby.lZtwm8.index Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001000000008 0x00007fff8e611cfb in tiny_free_list_remove_ptr ()
  44. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb zsh(49630) malloc: recording malloc stacks to disk using standard recorder zsh(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly ... Reading symbols for shared libraries ++............................ done miniruby(49630) malloc: recording malloc stacks to disk using standard recorder miniruby(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly miniruby(49630) malloc: stack logs deleted from /tmp/stack-logs.49630.arch. 2JF4tB.index miniruby(49630) malloc: stack logs being written into /tmp/stack-logs. 49630.miniruby.lZtwm8.index Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001000000008 0x00007fff8e611cfb in tiny_free_list_remove_ptr ()
  45. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb zsh(49630) malloc: recording malloc stacks to disk using standard recorder zsh(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly ... Reading symbols for shared libraries ++............................ done miniruby(49630) malloc: recording malloc stacks to disk using standard recorder miniruby(49630) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly miniruby(49630) malloc: stack logs deleted from /tmp/stack-logs.49630.arch. 2JF4tB.index miniruby(49630) malloc: stack logs being written into /tmp/stack-logs. 49630.miniruby.lZtwm8.index Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000001000000008 0x00007fff8e611cfb in tiny_free_list_remove_ptr ()
  46. (gdb) bt #0 0x00007fff8e611cfb in tiny_free_list_remove_ptr () #1 0x00007fff8e60e76d in szone_free_definite_size () #2 0x00007fff8e608898 in free () #3 0x000000010006f6cc in vm_xfree (objspace=0x10081c400, ptr=0x1004918b0) at gc.c:830 #4 0x000000010006fa76 in ruby_xfree (x=0x1004918b0) at gc.c:894 ...
  47. > malloc_history 49630 0x1004918b0 malloc_history Report Version: 2.0 Process: miniruby [49630] ... ALLOC 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | rb_class_new_instance | rb_obj_call_init | rb_funcall2 | rb_call | rb_call0 | vm_call0 | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | method_proc | rb_iterate | mlambda | rb_funcall | rb_call | rb_call0 | vm_call0 | call_cfunc | proc_lambda | rb_block_lambda | proc_new | rb_vm_make_proc | rb_proc_alloc | ruby_xmalloc | vm_xmalloc | malloc | malloc_zone_malloc ---- FREE 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_bmethod | rb_vm_invoke_proc | invoke_block_from_c | vm_yield_with_cfunc | bmcall | rb_method_call | rb_vm_call | vm_call0 | rb_threadptr_execute_interrupts | rb_threadptr_execute_interrupts_common | rb_gc_finalize_deferred | finalize_deferred | finalize_list | run_final | proc_free | ruby_xfree | vm_xfree | free
  48. > malloc_history 49630 0x1004918b0 malloc_history Report Version: 2.0 Process: miniruby [49630] ... ALLOC 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | rb_class_new_instance | rb_obj_call_init | rb_funcall2 | rb_call | rb_call0 | vm_call0 | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | method_proc | rb_iterate | mlambda | rb_funcall | rb_call | rb_call0 | vm_call0 | call_cfunc | proc_lambda | rb_block_lambda | proc_new | rb_vm_make_proc | rb_proc_alloc | ruby_xmalloc | vm_xmalloc | malloc | malloc_zone_malloc ---- FREE 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_bmethod | rb_vm_invoke_proc | invoke_block_from_c | vm_yield_with_cfunc | bmcall | rb_method_call | rb_vm_call | vm_call0 | rb_threadptr_execute_interrupts | rb_threadptr_execute_interrupts_common | rb_gc_finalize_deferred | finalize_deferred | finalize_list | run_final | proc_free | ruby_xfree | vm_xfree | free
  49. > malloc_history 49630 0x1004918b0 malloc_history Report Version: 2.0 Process: miniruby [49630] ... ALLOC 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | rb_class_new_instance | rb_obj_call_init | rb_funcall2 | rb_call | rb_call0 | vm_call0 | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | method_proc | rb_iterate | mlambda | rb_funcall | rb_call | rb_call0 | vm_call0 | call_cfunc | proc_lambda | rb_block_lambda | proc_new | rb_vm_make_proc | rb_proc_alloc | ruby_xmalloc | vm_xmalloc | malloc | malloc_zone_malloc ---- FREE 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_bmethod | rb_vm_invoke_proc | invoke_block_from_c | vm_yield_with_cfunc | bmcall | rb_method_call | rb_vm_call | vm_call0 | rb_threadptr_execute_interrupts | rb_threadptr_execute_interrupts_common | rb_gc_finalize_deferred | finalize_deferred | finalize_list | run_final | proc_free | ruby_xfree | vm_xfree | free
  50. > malloc_history 49630 0x1004918b0 malloc_history Report Version: 2.0 Process: miniruby [49630] ... ALLOC 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | rb_class_new_instance | rb_obj_call_init | rb_funcall2 | rb_call | rb_call0 | vm_call0 | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | method_proc | rb_iterate | mlambda | rb_funcall | rb_call | rb_call0 | vm_call0 | call_cfunc | proc_lambda | rb_block_lambda | proc_new | rb_vm_make_proc | rb_proc_alloc | ruby_xmalloc | vm_xmalloc | malloc | malloc_zone_malloc ---- FREE 0x1004918b0-0x1004918f7 [size=72]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_bmethod | rb_vm_invoke_proc | invoke_block_from_c | vm_yield_with_cfunc | bmcall | rb_method_call | rb_vm_call | vm_call0 | rb_threadptr_execute_interrupts | rb_threadptr_execute_interrupts_common | rb_gc_finalize_deferred | finalize_deferred | finalize_list | run_final | proc_free | ruby_xfree | vm_xfree | free
  51. BFGmalloc libgmalloc.dylib -- (Guard Malloc), an aggressive debugging malloc library
  52. BFGmalloc malloc gmalloc
  53. BFGmalloc malloc gmalloc
  54. BFGmalloc malloc gmalloc
  55. BFGmalloc malloc gmalloc
  56. BFGmalloc malloc gmalloc
  57. BFGmalloc malloc gmalloc
  58. BFGmalloc malloc gmalloc
  59. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) set environment DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb GuardMalloc[zsh-50147]: recording malloc stacks to disk using standard recorder GuardMalloc[zsh-50147]: stack logging compaction turned off; size of log files on disk can increase rapidly ...
  60. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) set environment DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb GuardMalloc[zsh-50147]: recording malloc stacks to disk using standard recorder GuardMalloc[zsh-50147]: stack logging compaction turned off; size of log files on disk can increase rapidly ...
  61. (gdb) set environment MallocStackLoggingNoCompact=true (gdb) set environment DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib (gdb) run ./bug.rb Starting program: /Users/jballanc/Source/ruby/miniruby ./bug.rb GuardMalloc[zsh-50147]: recording malloc stacks to disk using standard recorder GuardMalloc[zsh-50147]: stack logging compaction turned off; size of log files on disk can increase rapidly ...
  62. Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000000107203fe4 0x0000000100208b3c in rb_thread_mark (ptr=0x10085fce0) at vm.c:1733 1733! ! ! if (cfp->me) ((rb_method_entry_t *)cfp->me)->mark = 1; (gdb) p cfp->me $1 = (rb_method_entry_t *) 0x107203fe0
  63. Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000000107203fe4 0x0000000100208b3c in rb_thread_mark (ptr=0x10085fce0) at vm.c:1733 1733! ! ! if (cfp->me) ((rb_method_entry_t *)cfp->me)->mark = 1; (gdb) p cfp->me $1 = (rb_method_entry_t *) 0x107203fe0
  64. > malloc_history 50147 0x107203fe0 malloc_history Report Version: 2.0 Process: miniruby [50147] ... FREE 0x107203fe0-0x107203fff [size=32]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_bmethod | rb_vm_invoke_proc | invoke_block_from_c | vm_yield_with_cfunc | bmcall | rb_method_call | rb_vm_call | vm_call0 | call_cfunc | rb_str_reverse | rb_str_new_with_class | str_new | str_alloc | rb_newobj | gc_lazy_sweep | lazy_sweep | slot_sweep | obj_free | rb_free_m_table | st_foreach | free_method_entry_i | rb_free_method_entry | ruby_xfree | vm_xfree | GMfree | GMmalloc_zone_free
  65. > malloc_history 50147 0x107203fe0 malloc_history Report Version: 2.0 Process: miniruby [50147] ... FREE 0x107203fe0-0x107203fff [size=32]: thread_7fff732a5180 |start | main | ruby_run_node | ruby_exec_node | ruby_exec_internal | rb_iseq_eval_main | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_cfunc | call_cfunc | int_dotimes | rb_yield | rb_yield_0 | vm_yield | invoke_block_from_c | vm_exec | vm_exec_core | vm_call_method | vm_call_bmethod | rb_vm_invoke_proc | invoke_block_from_c | vm_yield_with_cfunc | bmcall | rb_method_call | rb_vm_call | vm_call0 | call_cfunc | rb_str_reverse | rb_str_new_with_class | str_new | str_alloc | rb_newobj | gc_lazy_sweep | lazy_sweep | slot_sweep | obj_free | rb_free_m_table | st_foreach | free_method_entry_i | rb_free_method_entry | ruby_xfree | vm_xfree | GMfree | GMmalloc_zone_free
  66. https://bugs.ruby-lang.org/issues/6171
  67. Questions? Joshua Ballanco @manhattanmetric https://github.com/jballanc

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
Advertisement