@@ -77,6 +77,7 @@ def check_fd_leak(test_name)
7777 end
7878 ( h [ fd ] ||= [ ] ) << [ io , autoclose , inspect ]
7979 }
80+ inspect = { }
8081 fd_leaked . select! { |fd |
8182 str = '' . dup
8283 pos = nil
@@ -98,6 +99,7 @@ def check_fd_leak(test_name)
9899 s = io . stat
99100 rescue Errno ::EBADF
100101 # something un-stat-able
102+ live2 . delete ( fd )
101103 next
102104 else
103105 next if /darwin/ =~ RUBY_PLATFORM and [ 0 , -1 ] . include? ( s . dev )
@@ -106,15 +108,35 @@ def check_fd_leak(test_name)
106108 io &.close
107109 end
108110 end
109- puts "Leaked file descriptor: #{ test_name } : #{ fd } #{ str } "
110- puts " The IO was created at #{ pos } " if pos
111+ inspect [ fd ] = [ str , pos ]
111112 true
112113 }
113114 unless fd_leaked . empty?
114115 unless @@try_lsof == false
115- @@try_lsof |= system ( *%W[ lsof -w -a -d #{ fd_leaked . minmax . uniq . join ( "-" ) } -p #$$ ] , out : Test ::Unit ::Runner . output )
116+ open_list = IO . popen ( %W[ lsof -w -a -d #{ fd_leaked . minmax . uniq . join ( "-" ) } -p #$$ ] , &:readlines )
117+ if @@try_lsof |= $?. success?
118+ columns = ( header = open_list . shift ) . split
119+ fd_index , node_index = columns . index ( 'FD' ) , columns . index ( 'NODE' )
120+ open_list . reject! do |of |
121+ of = of . chomp . split ( ' ' , node_index + 2 )
122+ if of [ node_index ] == 'TCP' and of . last . end_with? ( '(CLOSE_WAIT)' )
123+ fd = of [ fd_index ] . to_i
124+ inspect . delete ( fd )
125+ h . delete ( fd )
126+ live2 . delete ( fd )
127+ true
128+ else
129+ false
130+ end
131+ end
132+ end
133+ puts ( header , open_list ) unless open_list . empty?
116134 end
117135 end
136+ inspect . each { |fd , ( str , pos ) |
137+ puts "Leaked file descriptor: #{ test_name } : #{ fd } #{ str } "
138+ puts " The IO was created at #{ pos } " if pos
139+ }
118140 h . each { |fd , list |
119141 next if list . length <= 1
120142 if 1 < list . count { |io , autoclose , inspect | autoclose }
0 commit comments