From fd776274c91e338af1364b75fae48547c8214c45 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Mon, 18 Nov 2013 17:00:23 +0900 Subject: [PATCH] Additional fix for potential race condition which occurs when a user cancels a connection attempt - Fixes #1986 --- .../netty/channel/nio/AbstractNioChannel.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java b/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java index fd17e88cd2..d2abc804e8 100644 --- a/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java +++ b/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java @@ -167,10 +167,7 @@ public abstract class AbstractNioChannel extends AbstractChannel { boolean wasActive = isActive(); if (doConnect(remoteAddress, localAddress)) { - promise.setSuccess(); - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } + fulfillConnectPromise(promise, wasActive); } else { connectPromise = promise; requestedRemoteAddress = remoteAddress; @@ -215,6 +212,22 @@ public abstract class AbstractNioChannel extends AbstractChannel { } } + private void fulfillConnectPromise(ChannelPromise promise, boolean wasActive) { + // trySuccess() will return false if a user cancelled the connection attempt. + boolean promiseSet = promise.trySuccess(); + + // Regardless if the connection attempt was cancelled, channelActive() event should be triggered, + // because what happened is what happened. + if (!wasActive && isActive()) { + pipeline().fireChannelActive(); + } + + // If a user cancelled the connection attempt, close the channel, which is followed by channelInactive(). + if (!promiseSet) { + close(voidPromise()); + } + } + @Override public void finishConnect() { // Note this method is invoked by the event loop only if the connection attempt was @@ -226,10 +239,7 @@ public abstract class AbstractNioChannel extends AbstractChannel { try { boolean wasActive = isActive(); doFinishConnect(); - connectPromise.setSuccess(); - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } + fulfillConnectPromise(connectPromise, wasActive); } catch (Throwable t) { if (t instanceof ConnectException) { Throwable newT = new ConnectException(t.getMessage() + ": " + requestedRemoteAddress);