-
Bug
-
Resolution: Fixed
-
P3
-
1.4.0
-
hopper
-
x86
-
windows_2000
-
Verified
Name: nt126004 Date: 03/11/2002
FULL PRODUCT VERSION :
java version "1.4.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b91)
Java HotSpot(TM) Server VM (build 1.4.0-rc-b91, mixed mode)
Also in:
java version "1.4.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b91)
Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
ADDITIONAL OPERATING SYSTEMS :
Bug has also been observed, though in different form, on
Windows XP, version information is:
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
When issuing a non-blocking client-side connect using
SocketChannel and Selector, with the SocketChannel
registered for OP_CONNECT on the selector, if the host
specified in the connect is either non-existent or not
accepting connections (but is resolvable), the following is
seen:
- On Windows 2000 the selector never wakes up again with
the SelectionKey for the connecting channel selected. The
correct behavior would be that upon TCP failing the
connection, the selector would wakeup with that selection
key selected, marked isConnectable, and finishConnect would
then throw an exception such as NoRouteToHostException or
ConnectException. What in fact happens though is that the
aforementioned connect attempt is never heard from again.
- On Windows XP the selector does in fact wake up, and
finishConnect() completes successfully. This is in some
ways even worse, because you now think you have a valid
connection to a remote host that doesn't even exist. The
connection is furthermore even successfully writable, all
to a non-existent host.
In both cases I tested both attempting to connect to hosts
that were real but not accepting connections (such as
another machine on the same LAN), and to unassigned
addresses (in my case, I used 192.168.0.25), a private
address I know is unassigned, verified by attempting to
ping that address.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The attached source code is for a class called
TestNIOClient, which takes a hostname or dotted-decimal IP
address as a command line-parameter. Run it four times,
with the specified argument as follows in each case:
1. Specify the hostname of a known good web server. Try
www.google.com or java.sun.com
2. Specify an invalid hostname that you know won't
resolve. Try www.bogus.com
3. Specify a hostname of a device that is resolvable and
real, but is not running a web server or listening at port
80.
4. Specify a hostname or IP address that is resolvable, but
does not correspond to an actual physical device that could
be contacted. Try a private unassigned address. I used
192.168.0.25, but what you choose will have to depend on
your network configuration.
EXPECTED VERSUS ACTUAL BEHAVIOR :
1. Works correctly. Expected and actual result is:
Got event for our selection key.
Successful connect.
SUCCESS! Entire buffer contents were sent.
2. Works correctly. Expected and actual result is:
Connection failed:
java.net.UnknownHostException: www.bogus.com
at java.net.InetAddress.getAllByName0(InetAddress.java:920)
at java.net.InetAddress.getAllByName0(InetAddress.java:890)
at java.net.InetAddress.getAllByName(InetAddress.java:884)
at java.net.InetAddress.getByName(InetAddress.java:814)
at TestNIOClient.run(TestNIOClient.java:27)
at java.lang.Thread.run(Thread.java:536)
3. Fails differently on Win 2000 and Win XP. Expected
result on both platforms is that after a short interval,
the selector wakes up, and finishConnect() throws a
java.net.ConnnectException.
Actual results:
-Win 2K: No response ever. Program output as follows:
Elapsed time without response: 30 seconds.
Elapsed time without response: 60 seconds.
Elapsed time without response: 90 seconds.
Elapsed time without response: 120 seconds.
Elapsed time without response: 150 seconds.
Elapsed time without response: 180 seconds.
And so on forever. I have let this go as long as 17000
seconds just to see if it might eventually give up.
- On Win XP, false successful connect is seen. Output is:
Got event for our selection key.
Successful connect.
SUCCESS! Entire buffer contents were sent.
4. Fails differently on Win 2K and Windows XP. Expected
bahavior is that after a short interval, the selector wakes
up, and finishConnect() throws a java.net.NoRouteToHostException.
Actual behavior on each platform is as in 3.
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.nio.*;
import java.nio.channels.*;
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.util.*;
public class TestNIOClient implements Runnable
{
private Selector selector;
private SocketChannel sc;
private SelectionKey sk;
private String hostname;
private static final long INCREMENTAL_DELAY = 30L * 1000L; // Wakeup
interval of 30 seconds (30,000 ms)
private TestNIOClient(String hostname)
{
this.hostname = hostname;
new Thread(this).start();
}
public void run()
{
try
{
InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName
(hostname), 80);
sc = SocketChannel.open();
sc.configureBlocking(false);
selector = Selector.open();
sk = sc.register(selector, SelectionKey.OP_CONNECT);
if(sc.connect(isa))
{
System.out.println("Connected immediately!");
sc.close();
selector.close();
return;
}
else
{
ByteBuffer buf = ByteBuffer.allocateDirect(100);
buf.asCharBuffer().put(new String("The quick brown fox jumped
over the lazy dog.").toCharArray());
buf.flip();
long startTime = System.currentTimeMillis();
while(true)
{
selector.select(INCREMENTAL_DELAY);
Set selectedKeys = selector.selectedKeys();
if(selectedKeys.isEmpty())
{
System.out.println("Elapsed time without response: " +
(System.currentTimeMillis() -
startTime) / 1000L + " seconds.");
}
else if(!selectedKeys.contains(sk))
{
System.out.println("Got event about selection key other
than one we registered!");
}
else
{
System.out.println("Got event for our selection key.");
if(sk.isConnectable())
{
if(sc.finishConnect())
{
if(sc.isConnected())
{
System.out.println("Successful connect.");
sk.interestOps(SelectionKey.OP_WRITE);
sc.write(buf);
}
else
{
System.out.println("Finish connect
completed, but socket is not actually connected.");
}
}
else
{
System.out.println("Selection key incorrectly
indicated that socket channel was connectable.");
}
}
if(sk.isWritable() && (buf.remaining() > 0))
{
sc.write(buf);
}
if(buf.remaining() == 0)
{
System.out.println("SUCCESS! Entire buffer
contents were sent.");
sc.close();
selector.close();
return;
}
}
selectedKeys.clear();
}
}
}
catch(Exception e)
{
System.out.println("Connection failed:");
e.printStackTrace();
}
}
public static void main(String args[])
{
if(args.length > 0)
{
new TestNIOClient(args[0]);
}
else
{
System.out.println("\tUsage: TestNIOClient <hostname>");
}
}
}
---------- END SOURCE ----------
(Review ID: 139754)
======================================================================