Skip to content

Instantly share code, notes, and snippets.

@Vasfed
Created December 13, 2012 02:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Vasfed/4273437 to your computer and use it in GitHub Desktop.
Save Vasfed/4273437 to your computer and use it in GitHub Desktop.
Ruby Symbol#to_proc bug example
Ruby is 2.0.0-p-1 (ruby 2.0.0dev (2012-11-01 trunk 37411) [x86_64-darwin12.2.0])
A in ObjectSpace: 1
Proc is 70320301647720, object is 70320301647780
Object was not collected!
And will never be: here is the path from object to ruby VM:
,{"id":70320301647780,"bt":"T_OBJECT","class":70320301647860,"ivs":{}}
,{"id":70320301647740,"bt":"T_DATA","class":70320296186060,"type_name":"VM/env","size":96,"env":[70320301647780,70320301647740],"local_size":2,"prev_envval":null,"block":{"iseq":null,"self":"some_sym","class":null}}
,{"id":70320301647720,"bt":"T_DATA","class":70320296189040,"type_name":"proc","size":72,"is_lambda":0,"blockprocval":null,"envval":70320301647740,"block":{"iseq":70320301647760,"self":"some_sym","class":70320296248660}}
,{"id":70320295908000,"bt":"T_ARRAY","class":null,"val":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"full_name",70320295907760,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"to_sym",70320299984460,null,null,null,null,null,null,"some_sym",70320301647720]}
,{"id":70320296251960,"bt":"T_ARRAY","class":null,"val":[70320296251560,70320296247420,70320296238760,70320296236100,70320296236060,70320296235960,70320296235880,70320296235800,70320296235720,70320296235640,70320296235560,70320296235480,70320296235400,70320296235320,70320296235240,70320296235160,70320296235080,70320296235000,70320296234920,70320296234840,70320296234760,70320296234680,70320296234600,70320296234520,70320296234440,70320296234360,70320296234280,70320296234200,70320296234120,70320296234040,70320296233960,70320296233880,70320296233800,70320296233720,70320296233640,70320296233560,70320296233480,70320296233400,70320296233320,70320296233240,70320296233160,70320296233080,70320296233000,70320296232920,70320296232840,70320296232740,70320296232660,70320296232260,70320296232180,70320296232100,70320296232020,70320296231900,70320296231820,70320296231680,70320296231600,70320296231500,70320296231420,70320296231180,70320296231060,70320296230980,70320296222680,70320296222600,70320296222520,70320296222440,70320296222360,70320296222280,70320296222200,70320296222120,70320296222040,70320296221960,70320296221880,70320296221800,70320296221720,70320296221640,70320296221560,70320296221480,70320296221400,70320296221320,70320296221240,70320296221160,70320296221080,70320296221000,70320296220920,70320296220840,70320296220760,70320296220680,70320296220600,70320296220520,70320296220340,70320296220260,70320296220060,70320296219980,70320296219880,70320296219800,70320296219700,70320296219620,70320296219540,70320296219460,70320296219380,70320296219300,70320296219220,70320296219140,70320296219060,70320296216540,70320296216460,70320296216380,70320296215840,70320296214820,70320296205880,70320296205800,"\n",70320296202680,70320296202420,70320296200120,70320296199480,70320296198360,70320296198260,70320296198200,70320296189660,70320296189080,70320296188220,70320296187360,70320296186940,70320296186540,70320296186360,70320296186260,70320296186120,70320296186060,70320296184220,70320296183960,70320296183880,70320296183720,70320296182340,70320296182200,70320296182140,70320296182080,70320296182020,"_",70320296173360,70320296173260,70320296173200,70320296173140,"/",".eE","",70320296173020,"_","ruby",70320295888140,70320295887940,70320295908000,70320296003380,70320296021860,70320296021800,70320296021560,70320296021480,70320296021400,70320296021260,70320296055080,70320296054960,70320300281120,70320300725660,86400000000000,70320300249200,70320300249080,70320300248920,70320300248540,70320295992560,70320295991820,70320295991300,70320295991040,70320295990340,70320295988660,70320295987540,70320295986940,70320295985520,70320295975580,70320295975140,70320295974280,70320295974100,70320295973840,70320295973740,70320295973600,70320295973520,70320295973420,70320301698800,70320301698700,70320301698640,70320301698520]}
,{"id":70320296184120,"bt":"T_DATA","class":70320296186160,"type_name":"VM","size":1304,"thgroup_default":70320296182960,"mark_object_ary":70320296251960,"load_path":70320296189240,"loaded_features":70320296189180,"top_self":70320296252000,"coverages":null,"threads":["id",70367631233216]}
70320296184120 - is VM and is never collected :)
source :rubygems
gem 'colorize'
gem 'heap_dump', git:'git://github.com/Vasfed/heap_dump.git'
#!/usr/bin/env ruby
require 'bundler/setup'
require 'heap_dump'
require 'colorize'
puts "Ruby is #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_DESCRIPTION})"
if ARGV.size > 0
puts "Replacing native Symbol#to_proc.".red
class Symbol; def to_proc; proc{|a| a.send self }; end; end
end
class A
def get_block_id █ block.object_id; end
def some_method_with_symbol_to_proc
$id = object_id+1 # +1 is just to make grepping nicer; this is fixnum, no reference
get_block_id(&:some_sym)
end
end
def closure_method
#temporary object should be collected:
A.new.some_method_with_symbol_to_proc
end
def nop; end
proc_id = closure_method
nop # to clean register
HeapDump.dump($dump = 'dump.json', true) #calls gc
@id = $id - 1
puts "A in ObjectSpace: #{ObjectSpace.each_object(A){}}"
puts "\nProc is #{proc_id.to_s.green}, object is #{@id.to_s.red}"
if (s = `grep #{@id} #{$dump} | grep T_OBJECT`).empty?
puts "Wow, everything is ok (have you replaced the Symbol#to_proc call or using 1.9.2?)".green
else
puts "Object was not collected!".red
puts "And will never be: here is the path from object to ruby VM:"
def colored_puts str
puts @colors.inject(str){|str,(s,c)| str.gsub(s.to_s, "#{s}".colorize(c))}
str
end
def inspection_step color
(s = `grep #{@id} #{$dump} | grep -v id\\":#{@id} | grep -v #{@id.to_i + 1}`) =~ /,\{"id":(\d+)/
@colors[@id = $1] = color
colored_puts s
end
@colors = {@id => :red}
colored_puts s
([:yellow, :green, :blue, :magenta, :cyan]*3).each{|c|
if inspection_step(c) =~ /"type_name":"VM"/
colored_puts "#{@id} - is VM and is never collected :)"
break
end
}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment