javaee / grizzly

Writing scalable server applications in the Java™ programming language has always been difficult. Before the advent of the Java New I/O API (NIO), thread management issues made it impossible for a server to scale to thousands of users. The Grizzly NIO framework has been designed to help developers to take advantage of the Java™ NIO API.
https://javaee.github.io/grizzly/
Other
222 stars 60 forks source link

grizzly may not throw IOException when failing to connect #1807

Closed glassfishrobot closed 9 years ago

glassfishrobot commented 9 years ago

there are times when

NIOTransport.connect().get()

should throw an IOException, yet does not and the call "succeeds".

here's code to reproduce the issue:

public static void main(String[] args) throws Throwable {
        InetSocketAddress destination = new InetSocketAddress("localhost", 60666);
        for (int i=0; i<1000000; i++) {
            if (i % 10000 == 0) {
System.err.println("iteration " + i);
            }
            NIOTransport transport = null;
            try {
NIOTransportBuilder builder = TCPNIOTransportBuilder.newInstance();
transport = builder.build();
transport.start();
transport.connect(destination).get();
Assert.fail("connection expected to fail. connected at attempt " + i);
            } catch (Throwable t) {
Throwable cause = getRootCause(t);
if ((cause instanceof ConnectException) && "Connection refused".equals(cause.getMessage())) {
    //this is expected
    continue;
}
throw t;
            } finally {
if (transport != null) {
    transport.shutdown().get();
}
            }
        }
    }

    public static Throwable getRootCause(Throwable t) {
        Throwable cause = t;
        while (cause.getCause() != null && cause.getCause() != cause) {
            cause = cause.getCause();
        }
        return cause;
    }

on my machine, it prints the following:

iteration 0
iteration 10000
iteration 20000
Exception in thread "main" java.lang.AssertionError: connection expected to fail. connected at attempt 28206

Environment

  1. uname -a Linux bob 4.1.8-200.fc22.x86_64 #1 SMP Tue Sep 22 12:13:21 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

  2. java -version openjdk version "1.8.0_60" OpenJDK Runtime Environment (build 1.8.0_60-b27) OpenJDK 64-Bit Server VM (build 25.60-b23, mixed mode)

    Affected Versions

    [2.3.23]

glassfishrobot commented 9 years ago

Reported by radai

glassfishrobot commented 9 years ago

@rlubke said: Interesting. On MacOS 10.11.1, I get:

iteration 0 iteration 10000 Exception in thread "main" java.util.concurrent.ExecutionException: java.net.SocketException: Invalid argument at org.glassfish.grizzly.impl.ReadyFutureImpl.get(ReadyFutureImpl.java:204) at org.glassfish.grizzly.GrizzlyVersionTest.main(GrizzlyVersionTest.java:73) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) Caused by: java.net.SocketException: Invalid argument at sun.nio.ch.Net.connect0(Native Method) at sun.nio.ch.Net.connect(Net.java:465) at sun.nio.ch.Net.connect(Net.java:457) at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:670) at org.glassfish.grizzly.nio.transport.TCPNIOConnectorHandler.connectAsync(TCPNIOConnectorHandler.java:137) at org.glassfish.grizzly.AbstractSocketConnectorHandler.connect(AbstractSocketConnectorHandler.java:91) at org.glassfish.grizzly.AbstractSocketConnectorHandler.connect(AbstractSocketConnectorHandler.java:79) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.connect(TCPNIOTransport.java:344) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.connect(TCPNIOTransport.java:86)

glassfishrobot commented 9 years ago

@rlubke said: I believe this is a bug in your test case.

You're attempting to connect to a port in the ephemeral range. When you do this in a loop, the clients are being assigned different ephemeral ports throughout the test. At one point, the client port is the same as the faux server port and the connect event, at least on linux, goes through.

It appears that MacOS behaves differently here. Not sure what win32 does.

If I adjust the test to use a non-ephemeral port that I know is not bound on the system (say 444), there are no problems.

glassfishrobot commented 7 years ago

This issue was imported from java.net JIRA GRIZZLY-1807

glassfishrobot commented 9 years ago

Marked as invalid on Thursday, October 15th 2015, 7:19:30 pm