ruby-changes:34075
From: akr <ko1@a...>
Date: Tue, 27 May 2014 12:24:59 +0900 (JST)
Subject: [ruby-changes:34075] akr:r46156 (trunk): * test/lib/minitest/unit.rb: Show leaked file descriptors.
akr 2014-05-27 12:24:52 +0900 (Tue, 27 May 2014) New Revision: 46156 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=46156 Log: * test/lib/minitest/unit.rb: Show leaked file descriptors. Modified files: trunk/ChangeLog trunk/test/lib/minitest/unit.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 46155) +++ ChangeLog (revision 46156) @@ -1,3 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue May 27 12:24:22 2014 Tanaka Akira <akr@f...> + + * test/lib/minitest/unit.rb: Show leaked file descriptors. + Tue May 27 11:12:56 2014 Nobuyoshi Nakada <nobu@r...> * io.c (rb_io_fileno, rb_io_inspect): non-modification does not Index: test/lib/minitest/unit.rb =================================================================== --- test/lib/minitest/unit.rb (revision 46155) +++ test/lib/minitest/unit.rb (revision 46156) @@ -932,6 +932,7 @@ module MiniTest https://github.com/ruby/ruby/blob/trunk/test/lib/minitest/unit.rb#L932 } threads = find_threads + fds = find_fds tempfiles = find_tempfiles assertions = filtered_test_methods.map { |method| @@ -949,6 +950,8 @@ module MiniTest https://github.com/ruby/ruby/blob/trunk/test/lib/minitest/unit.rb#L950 threads = check_thread_leak inst, threads, find_threads + fds = check_fd_leak inst, fds, find_fds + # find_tempfiles is too slow to run for each test method. #tempfiles = check_tempfile_leak inst, tempfiles, find_tempfiles @@ -982,6 +985,60 @@ module MiniTest https://github.com/ruby/ruby/blob/trunk/test/lib/minitest/unit.rb#L985 } end live2 + end + + def find_fds + fd_dir = "/proc/#{$$}/fd" + if File.directory?(fd_dir) + Dir.entries(fd_dir).grep(/\A\d+\z/).map(&:to_i).sort + else + [] + end + end + + def check_fd_leak(inst, live1, live2) + name = "#{inst.class}\##{inst.__name__}" + fd_closed = live1 - live2 + if !fd_closed.empty? + fd_closed.each {|fd| + puts "Closed file descriptor: #{name}: #{fd}" + } + end + fd_leaked = live2 - live1 + if !fd_leaked.empty? + h = {} + ObjectSpace.each_object(IO) {|io| + begin + fd = io.fileno + rescue IOError # closed IO object + next + end + (h[fd] ||= []) << io + } + fd_leaked.each {|fd| + str = '' + if h[fd] + str << ' :' + h[fd].map {|io| + s = ' ' + io.inspect + s << "(not-autoclose)" if !io.autoclose? + s + }.each {|s| + str << s + } + end + puts "Leaked file descriptor: #{name}: #{fd}#{str}" + } + h.each {|fd, ios| + next if ios.length <= 1 + list = ios.map {|io| [io, io.autoclose?] } + if 1 < list.count {|io, autoclose| autoclose } + str = list.map {|io, autoclose| " #{io.inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join + puts "Multiple autoclose IO object for a file descriptor:#{str}" + end + } + end + live2 end def find_tempfiles -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/