ruby-changes:58720
From: Yusuke <ko1@a...>
Date: Tue, 12 Nov 2019 01:47:47 +0900 (JST)
Subject: [ruby-changes:58720] c02de30efb (master): tool/lib/leakchecker.rb: show the code location that allocated leaked fd
https://git.ruby-lang.org/ruby.git/commit/?id=c02de30efb From c02de30efbca2a2d89cdf188a27991f7ae15b9da Mon Sep 17 00:00:00 2001 From: Yusuke Endoh <mame@r...> Date: Tue, 12 Nov 2019 01:30:42 +0900 Subject: tool/lib/leakchecker.rb: show the code location that allocated leaked fd by using ObjectSpace.trace_object_allocations. `make test-all LEAK_CHECKER_TRACE_OBJECT_ALLOCATION=true` will print not only leaked fds but also where it was created. diff --git a/tool/lib/leakchecker.rb b/tool/lib/leakchecker.rb index af9200b..26ece93 100644 --- a/tool/lib/leakchecker.rb +++ b/tool/lib/leakchecker.rb @@ -75,9 +75,13 @@ class LeakChecker https://github.com/ruby/ruby/blob/trunk/tool/lib/leakchecker.rb#L75 } fd_leaked.each {|fd| str = ''.dup + pos = nil if h[fd] str << ' :' h[fd].map {|io, autoclose, inspect| + if ENV["LEAK_CHECKER_TRACE_OBJECT_ALLOCATION"] + pos = "#{ObjectSpace.allocation_sourcefile(io)}:#{ObjectSpace.allocation_sourceline(io)}" + end s = ' ' + inspect s << "(not-autoclose)" if !autoclose s @@ -86,6 +90,7 @@ class LeakChecker https://github.com/ruby/ruby/blob/trunk/tool/lib/leakchecker.rb#L90 } end puts "Leaked file descriptor: #{test_name}: #{fd}#{str}" + puts " The IO was created at #{pos}" if pos } #system("lsof -p #$$") if !fd_leaked.empty? h.each {|fd, list| diff --git a/tool/lib/minitest/unit.rb b/tool/lib/minitest/unit.rb index 90d2da2..8ac0f14 100644 --- a/tool/lib/minitest/unit.rb +++ b/tool/lib/minitest/unit.rb @@ -941,28 +941,36 @@ module MiniTest https://github.com/ruby/ruby/blob/trunk/tool/lib/minitest/unit.rb#L941 leakchecker = LeakChecker.new - assertions = filtered_test_methods.map { |method| - inst = suite.new method - inst._assertions = 0 + continuation = proc do + assertions = filtered_test_methods.map { |method| + inst = suite.new method + inst._assertions = 0 - print "#{suite}##{method} = " if @verbose + print "#{suite}##{method} = " if @verbose - start_time = Time.now if @verbose - result = inst.run self + start_time = Time.now if @verbose + result = inst.run self - print "%.2f s = " % (Time.now - start_time) if @verbose - print result - puts if @verbose - $stdout.flush + print "%.2f s = " % (Time.now - start_time) if @verbose + print result + puts if @verbose + $stdout.flush - unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # compiler process is wrongly considered as leak - leakchecker.check("#{inst.class}\##{inst.__name__}") - end + unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # compiler process is wrongly considered as leak + leakchecker.check("#{inst.class}\##{inst.__name__}") + end - inst._assertions - } + inst._assertions + } + return assertions.size, assertions.inject(0) { |sum, n| sum + n } + end - return assertions.size, assertions.inject(0) { |sum, n| sum + n } + if ENV["LEAK_CHECKER_TRACE_OBJECT_ALLOCATION"] + require "objspace" + ObjectSpace.trace_object_allocations(&continuation) + else + continuation.call + end end ## -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/