[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]