diff --git a/src/main/java/org/jboss/netty/channel/socket/nio/NioClientSocketPipelineSink.java b/src/main/java/org/jboss/netty/channel/socket/nio/NioClientSocketPipelineSink.java index 72cf69a1a0..cc499b6c75 100644 --- a/src/main/java/org/jboss/netty/channel/socket/nio/NioClientSocketPipelineSink.java +++ b/src/main/java/org/jboss/netty/channel/socket/nio/NioClientSocketPipelineSink.java @@ -133,19 +133,25 @@ class NioClientSocketPipelineSink extends AbstractChannelSink { } private void connect( - final NioClientSocketChannel channel, ChannelFuture future, + final NioClientSocketChannel channel, final ChannelFuture cf, SocketAddress remoteAddress) { try { if (channel.socket.connect(remoteAddress)) { - channel.worker.register(channel, future); + channel.worker.register(channel, cf); } else { - future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); - channel.connectFuture = future; + channel.getCloseFuture().addListener(new ChannelFutureListener() { + public void operationComplete(ChannelFuture f) + throws Exception { + cf.setFailure(new ClosedChannelException()); + } + }); + cf.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); + channel.connectFuture = cf; boss.register(channel); } } catch (Throwable t) { - future.setFailure(t); + cf.setFailure(t); fireExceptionCaught(channel, t); } } @@ -363,7 +369,7 @@ class NioClientSocketPipelineSink extends AbstractChannelSink { ch.connectFuture.setFailure(cause); fireExceptionCaught(ch, cause); - close(k); + NioWorker.close(ch, succeededFuture(ch)); } } } @@ -378,13 +384,12 @@ class NioClientSocketPipelineSink extends AbstractChannelSink { } catch (Throwable t) { ch.connectFuture.setFailure(t); fireExceptionCaught(ch, t); - close(k); + NioWorker.close(ch, succeededFuture(ch)); } } private void close(SelectionKey k) { - k.cancel(); - NioSocketChannel ch = (NioSocketChannel) k.attachment(); + NioClientSocketChannel ch = (NioClientSocketChannel) k.attachment(); NioWorker.close(ch, succeededFuture(ch)); } } diff --git a/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramWorker.java b/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramWorker.java index d94d1c8817..ee7e7e0b0d 100644 --- a/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramWorker.java +++ b/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramWorker.java @@ -653,26 +653,12 @@ class NioDatagramWorker implements Runnable { static void close(final NioDatagramChannel channel, final ChannelFuture future) { NioDatagramWorker worker = channel.worker; - Selector selector = worker.selector; boolean connected = channel.isConnected(); boolean bound = channel.isBound(); try { - // It is necessary to cancel all keys before closing a socket - // because the shutdown flag in the Selector loop is set only when - // all keys are cancelled. Thus, DatagramChannel.close() and - // SelectionKey.cancel() must be placed in a synchronized block. - // Otherwise DatagramChannel.register() in RegisterTask can be called - // after cancel(), but before close(), resulting in the infinite - // Selector loop that refuses to shut down due to the dangling keys. - synchronized (channel.interestOpsLock) { - SelectionKey key = channel.getDatagramChannel().keyFor(selector); - if (key != null) { - key.cancel(); - worker.cancelledKeys ++; - } - channel.getDatagramChannel().close(); - } + channel.getDatagramChannel().close(); + worker.cancelledKeys ++; if (channel.setClosed()) { future.setSuccess(); diff --git a/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java b/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java index dfb686a327..9af14ad5a2 100644 --- a/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java +++ b/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java @@ -573,26 +573,12 @@ class NioWorker implements Runnable { static void close(NioSocketChannel channel, ChannelFuture future) { NioWorker worker = channel.worker; - Selector selector = worker.selector; boolean connected = channel.isConnected(); boolean bound = channel.isBound(); try { - // It is necessary to cancel all keys before closing a socket - // because the shutdown flag in the Selector loop is set only when - // all keys are cancelled. Thus, SocketChannel.close() and - // SelectionKey.cancel() must be placed in a synchronized block. - // Otherwise SocketChannel.register() in RegisterTask can be called - // after cancel(), but before close(), resulting in the infinite - // Selector loop that refuses to shut down due to the dangling keys. - synchronized (channel.interestOpsLock) { - SelectionKey key = channel.socket.keyFor(selector); - if (key != null) { - key.cancel(); - worker.cancelledKeys ++; - } - channel.socket.close(); - } + channel.socket.close(); + worker.cancelledKeys ++; if (channel.setClosed()) { future.setSuccess();