uncutstone
5/15/2006 3:37:00 PM
It is really a triky problem. My OS is windows 98, ruby version is ruby
1.8.2 (2004-12-25) [i386-mswin32].
Following code is used to illustrate the problem I encountered. Before
you execute it, please ensure to be offline, so it can be run very fast
.. Please notice the line in tcpclient.rb "145.times do", it is the
key issue.
Let me explain it.
Tcpserver.rb is a local tcp server simply sends a hello message
whenever a client is connected. Tcpclient.rb first makes a connect to
the local tcp server( this connection will be read later), then tries
many times to connect to a bad ip addresses which indeed can never be
connected. So every try will raise a exception " Unknown Error -
connect(2)". This exception is simply ignored and the client
continues trying.
The wiered thing is , after certain number of tries, the established
connection between the tcp client and the local tcp server is broken.
So the line "goodConn.gets" also raises a exception . Even more,
what exception "goodConn.gets" raised is realted to the number of
tries to connect to the bad ip.
a. if times is less than 140 , it acts normally, nothing wrong, a hello
message is received from the local tcp server. I got this:
Exception raised: Unknown Error - connect(2)
Hello from local tcp server
b. If 140< times <145, I got this :
Exception raised: Unknown Error - connect(2)
tcpclient.rb:19:in `gets': Bad file descriptor (Errno::EBADF)
from tcpclient.rb:19:in `testsocket'
from tcpclient.rb:24
c. if times > 145, I got this:
Exception raised: Unknown Error - connect(2)
tcpclient.rb:19:in `gets': Invalid argument (Errno::EINVAL)
from tcpclient.rb:19:in `testsocket'
from tcpclient.rb:24
General speaking, it seems a resource leak happens every time a
"Unknown Error-connect(2)" exception raised when the tcpclient
failed to connnect to a bad ip address. So after a substantial number
of tries, the leak accumulates and the socket is crushed. Is it a bug
of socket library??
Code is listed below, if you are insterested, please try it, run the
ftpserver.rb first.
1. tcpserver.rb:
require 'socket'
server = TCPServer.new('localhost',21)
while(session = server.accept)
session.print "Hello from local tcp server"
session.close
end
2. tcpclient.rb:
require 'socket'
def testsocket
goodAddr = "localhost"
goodConn = TCPSocket.new(goodAddr,21)
badAddr = "137.144.70.12" #no connection could established on this
address
145.times do
badconn = nil
begin
badconn = TCPSocket.new(badAddr,21)
rescue Exception => aException
puts "Exception raised: #{aException.to_s}"
ensure
badconn.close if @badconn and not @badconn.closed?
end
end
s = goodConn.gets
puts s
goodConn.close
end
testsocket