netty/netty — Issue #138: client connect exception
Author: liyongqi
Created: 2011-12-21 04:33:16+00:00
State: open

hi,

I am a new user of Netty(really a very good nio project), and I use
netty to do some delay test of web server. But I found some strange
exception, and I can not understand it, I trace the netty source code,
when exception throws, k.isValid() is false, it is a bug or
how can I avoid it?

here is the netty code:

NioClientSocketPipelineSink.java

private void processConnectTimeout(Set keys,
long currentTimeNanos) {
ConnectException cause = null;
for (SelectionKey k: keys) {
if (!k.isValid()) {
close(k);
continue;
}

NioClientSocketChannel ch = (NioClientSocketChannel)
k.attachment();
if (ch.connectDeadlineNanos > 0 &&
currentTimeNanos >= ch.connectDeadlineNanos) {

if (cause == null) {
cause = new ConnectException("connection timed out");
}

ch.connectFuture.setFailure(cause);
fireExceptionCaught(ch, cause);
ch.worker.close(ch, succeededFuture(ch));
}
}
}

Here is my test code:

import java.net.*;
import java.util.concurrent.*;

import org.jboss.netty.bootstrap.*;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.*;
import org.jboss.netty.handler.codec.http.*;

public class DelayNIO2
{
public static final String addr = "192.168.101.200";
public static final int port = 80;

private static NioClientSocketChannelFactory fact4Client = new
NioClientSocketChannelFactory(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());

public DelayNIO2()
{}

public static void main(String[] args)
{
while(true)
{
for(int i = 0; i < 16; i++)
{
DelayNIO2 nio = new DelayNIO2();
nio.run();
}
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

public void run()
{
try
{
ClientBootstrap cb = new ClientBootstrap(fact4Client);
cb.setOption("reuseAddress", false);

int timeout = 1000;
cb.setOption("connectTimeoutMillis", timeout);

cb.setPipelineFactory(new ChannelPipelineFactory()
{
public ChannelPipeline getPipeline() throws Exception
{
return Channels.pipeline(new HttpRequestEncoder(),
new HttpResponseDecoder(), new Handler4HttpDelay2());
}
});

ChannelFuture f = cb.connect(new InetSocketAddress(addr, port));
f.addListener(new ChannelFutureListener()
{
public void operationComplete(ChannelFuture future)
throws Exception
{
if (future.isSuccess())
{
HttpMethod method = HttpMethod.GET;
HttpVersion version = HttpVersion.HTTP_1_1;
HttpRequest httpRequest = new
DefaultHttpRequest(version, method, "/");
httpRequest.setHeader("Host", addr + (port == 80 ?
"" : ":" + port));
httpRequest.setHeader("Accept", "*/*");
httpRequest.setHeader("User-Agent", "Mozilla/4.0
(compatible; MSIE 6.0; Windows NT 5.0; Trident/4.0)");
httpRequest.setHeader("Connection", "close");
future.getChannel().write(httpRequest);
}
else
{
future.getCause().printStackTrace();
future.getChannel().close();
}
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

class Handler4HttpDelay2 extends SimpleChannelHandler
{
private long start = 0;

public Handler4HttpDelay2()
{}

public void channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception
{
start = System.currentTimeMillis();
}

public void messageReceived(ChannelHandlerContext ctx, final
MessageEvent e) throws Exception
{
System.out.println(Thread.currentThread());
long now = System.currentTimeMillis();
int milseconds = (int)(now - start);
try
{
e.getChannel().close();
}
catch(Exception e2)
{}
System.out.println("Delay is " + milseconds);
}

public void exceptionCaught(ChannelHandlerContext ctx,
ExceptionEvent e) throws Exception
{
e.getCause().printStackTrace();
try
{
e.getChannel().close();
}
catch(Exception e2)
{}
}
}

Here is the excetpion:

...
Thread[New I/O client worker #1-4,5,main]
Delay is 0
java.nio.channels.ClosedChannelException
at org.jboss.netty.channel.socket.nio.NioClientSocketPipelineSink$1.operationComplete(NioClientSocketPipelineSink.java:157)
at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:381)
at org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:367)
at org.jboss.netty.channel.DefaultChannelFuture.setSuccess(DefaultChannelFuture.java:316)
at org.jboss.netty.channel.AbstractChannel$ChannelCloseFuture.setClosed(AbstractChannel.java:351)
at org.jboss.netty.channel.AbstractChannel.setClosed(AbstractChannel.java:188)
at org.jboss.netty.channel.socket.nio.NioSocketChannel.setClosed(NioSocketChannel.java:146)
at org.jboss.netty.channel.socket.nio.NioWorker.close(NioWorker.java:592)
at org.jboss.netty.channel.socket.nio.NioClientSocketPipelineSink$Boss.close(NioClientSocketPipelineSink.java:415)
at org.jboss.netty.channel.socket.nio.NioClientSocketPipelineSink$Boss.processConnectTimeout(NioClientSocketPipelineSink.java:379)
at org.jboss.netty.channel.socket.nio.NioClientSocketPipelineSink$Boss.run(NioClientSocketPipelineSink.java:299)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:44)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Thread[New I/O client worker #1-2,5,main]
Delay is 0
...