[2471] in java-interest
Bug in Socket.accept()/close() ?
daemon@ATHENA.MIT.EDU (Bob Beck)
Tue Oct 3 01:41:51 1995
Date: Mon, 2 Oct 95 10:42 PDT
To: java-interest@java.sun.com
From: Bob Beck <rbk@ibeam.jf.intel.com>
Cc: Arthur.Vanhoff@Eng.Sun.COM
I think I've found a bug in Socket.accept() and close(). I have a simple
client and server application (in Alpha3, based on net.NetworkClient and
net.NetworkServer) where the server is a minor extension over
serviceRequest(), and the client is in a loop attempting to create a
connection then shut it down. On my NT3.51 system, after about 12000
connections are created on the server, the server process fails with an out
of memory exception and can't be recovered (other than killing the server
process and restarting it).
After some digging, it looks like the server process is constantly
accumulating OS handles. I have verified the code is calling close() on the
per connection socket, and that the threads are terminating (I have a
different version of the server based on my own variant of NetworkServer
that reuses threads and handles more exceptions, and it fails in this one also).
To see it accumulating handles, use perfmon, look at the "Handle Count"
counter in the "process" object for each of the java processes (the one
running DumbClient and the one running DumbServer). The client process has
a (roughly) constant number of handles, the server process handle count
climbs until it gets the error. This suggests that the Java VM isn't
closing enough handles in the NT implementation. I haven't tried this on a
SUN implementation.
BTW: if I remove the Thread.sleep(50); from the client process, the client
can hang; it behaves as if the server doesn't see it. Starting another
client process seems to make them both recover. Any ideas?
Code is attached below.
- Bob Beck
DumbServer.java:
import java.io.*;
import net.NetworkServer;
import net.InetAddress;
public class DumbServer extends NetworkServer
{
static final int MyPort = 5308;
static int connCount = 0;
public static void main(String args[])
{
new DumbServer().startServer(MyPort);
}
public static synchronized int newConn() { return ++connCount; }
public void serviceRequest()
{
int thisConn = newConn();
byte buf[] = new byte[300];
int n;
clientOutput.print("Echo server " + getClass().getName()
+ " on " + InetAddress.localHostName
+ " conn# " + thisConn + "\n");
clientOutput.flush();
while ((n = clientInput.read(buf, 0, buf.length)) >= 0) {
if (buf[0] == 'Q') {
clientOutput.print("Closing Connection!" + "\n");
clientOutput.flush();
break;
}
clientOutput.write(buf, 0, n);
clientOutput.flush();
}
}
}
DumbClient.java:
import java.io.*;
import net.NetworkClient;
import net.InetAddress;
public class DumbClient extends NetworkClient
{
static final int MyPort = 5308;
public static void main(String args[])
{
for (int i = 0;; ++i) {
System.out.println(i);
DumbClient dc;
try {
dc = new DumbClient(InetAddress.getLocalHostName(), MyPort);
dc.Process();
dc.closeServer();
} catch (Exception e) {
System.out.println("Oops!");
e.printStackTrace();
break;
}
Thread.sleep(50);
}
}
public void Process()
{
byte buf[] = new byte[300];
System.out.print("r0:");
int n = serverInput.read(buf); // synch with server thread starting
System.out.println(n);
serverOutput.println("Hello!");
System.out.print("r1:");
n = serverInput.read(buf);
System.out.println(n);
System.out.println("Q");
serverOutput.println("Q"); // shut down the connection
}
public DumbClient(String host, int port) { super(host, port); }
}
--
Bob Beck rbk@ibeam.intel.com CompuServe: 71674,106
Intel Corporation (503)264-8856 AOL: RDBeck
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com