I have a small script which scans all the ips ranging from 192.168.190.xxx to 192.168.220.xxx on port 411.
The script works fine sometimes, but sometimes I get the error “No buffer space available”
dcport.rb:8:ininitialize’: No buffer space available – connect(2) (Errno::ENOBUFS)`
I have read that this occurs when the socket were not closed properly, but I have used mysocket.close to prevent that which I suppose does not work properly.
How to prevent this from happening, I mean how to close the socket properly?
My code is as follows
require 'socket'
require 'timeout'
(190...216).each do |i|
(0...255).each do |j|
begin
#puts "Scanning 192.168.#{i}.#{j}"
scan=Timeout::timeout(10/1000.0) {
s=TCPSocket.new("192.168.#{i}.#{j}",411)
s.close
puts "192.168.#{i}.#{j} => Hub running"
}
rescue Timeout::Error
rescue Errno::ENETUNREACH
rescue Errno::ECONNREFUSED
end
end
end
My guess is that, sometimes, the timeout fires between the socket creation and the socket closing, which makes you leak some sockets. Since (as far as a quick google search told me), ENOBUFS happens by default after 1024 sockets opened, that could definitely be it.
Timeout, as well as Thread.raise, is very harmful in situations where you need to be sure that something happens (in your case, s.close), as you actually cannot guarantee it anymore: the exception could be raised anywhere, even within an ensure block.
In your case, I think that you could fix it by adding an ensure clause outside the timeout block (untested code follows):