-
Bug
-
Resolution: Fixed
-
P3
-
1.4.0
-
rc
-
x86
-
linux
-
Verified
###@###.### 2001-12-21
J2SE Version (please include all output from java -version flag):
1.4 CAP build #88 (also reproducable on build #82)
% java -version
java version "1.4.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b88)
Java HotSpot(TM) Client VM (build 1.4.0-rc-b88, mixed mode)
Does this problem occur on J2SE 1.3? Yes / No (pick one)
N.A. its a NIO bug
Operating System Configuration Information (be specific):
Redhat Linux 6.2 (Kernel 2.2.16)
Also reproducable on Redhat Linux 6.1 (2.2.12) running CAP build #82
Hardware Configuration Information (be specific):
i586 linux boxes. One with a pentium, one with an AMD K6
Bug Description:
Attached a simple non-blocking server program(NonBlockingServer.java)
using the Selector class. It works fine until a client forcibly
disconnects. Then the Selector.select() call stops blocking and starts
immediately returning a zero-length set of SelectionKeys. It is not
blocking because one of the client channels has closed, but it isn't
putting the corresponding key into the ready set.
The server does continue to handle requests from other connected
clients. The problem is that it is no longer blocking. Instead, the
select() call returns immediately, so it is effectively converted to a
very innefficient polling server. Closed channels and their selection
keys never get cancelled and removed from the selector's set of keys.
Frist tried to workaround the problem by checking for a zero-length
return value, and when I find such a ready set going and looping through the
complete set of registered keys, looking for one that has been
closed. Unfortunately, that didn't help because none of the channels (or
their underlying sockets) reports that it is closed.(See attached workaround
section in the sample code)
So tried another workaround by checking the return value of read() call.
If it returns -1, then you know that the client has disconnected,
and you can close the channel and cancel the key.
The workaround for the sample code is to change this line:
client.read(buffer);
To these:
int bytesread = client.read(buffer);
// If read() returns -1, it indicates end-of-stream, which
// means the client has disconnected, so de-register the
// selection key and close the channel.
if (bytesread == -1) {
key.cancel();
client.close();
continue;
}
Note, however, that there is still a bug: the select() call is supposed
to block and return a non-empty Set of selection keys, it should not have
broken the select() method!
Need to include a non-blocking server example like this in the 4th edition
of the book Java in a Nutshell, but not be able to get this bug sorted out
quickly before the book goes into production!
Steps to Reproduce (be specific):
1) Compile and run the program below.
2) Connect to the server on port 8000 using telnet:
telnet localhost 8000
3) Disconnect the client. Typically this involves typing the ^] escape
character and then typing "close" or "quit".
4) You should see the server start to spew debugging messages indicating
that the select call has stopped blocking.