Fixed NETTY-381 channelDisconnected event is sometimes not triggered when Channel.close() is called by multiple threads.

* Internal state variable should never be set to ST_CLOSED until the close channel future is set
This commit is contained in:
Trustin Lee 2011-02-01 13:39:20 +09:00
parent a8f3353d7c
commit 78104cbd28
2 changed files with 21 additions and 4 deletions

View File

@ -27,6 +27,7 @@ import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.DefaultChannelConfig;
@ -47,7 +48,7 @@ final class DefaultLocalChannel extends AbstractChannel implements LocalChannel
private static final int ST_BOUND = 1;
private static final int ST_CONNECTED = 2;
private static final int ST_CLOSED = -1;
private final AtomicInteger state = new AtomicInteger(ST_OPEN);
final AtomicInteger state = new AtomicInteger(ST_OPEN);
private final ChannelConfig config;
private final ThreadLocalBoolean delivering = new ThreadLocalBoolean();
@ -62,6 +63,15 @@ final class DefaultLocalChannel extends AbstractChannel implements LocalChannel
super(parent, factory, pipeline, sink);
this.pairedChannel = pairedChannel;
config = new DefaultChannelConfig();
// TODO Move the state variable to AbstractChannel so that we don't need
// to add many listeners.
getCloseFuture().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
state.set(ST_CLOSED);
}
});
fireChannelOpen(this);
}
@ -101,7 +111,6 @@ final class DefaultLocalChannel extends AbstractChannel implements LocalChannel
@Override
protected boolean setClosed() {
state.set(ST_CLOSED);
return super.setClosed();
}

View File

@ -29,6 +29,7 @@ import org.jboss.netty.channel.AbstractChannel;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.MessageEvent;
@ -50,7 +51,7 @@ class NioSocketChannel extends AbstractChannel
private static final int ST_BOUND = 1;
private static final int ST_CONNECTED = 2;
private static final int ST_CLOSED = -1;
private volatile int state = ST_OPEN;
volatile int state = ST_OPEN;
final SocketChannel socket;
final NioWorker worker;
@ -82,6 +83,14 @@ class NioSocketChannel extends AbstractChannel
this.socket = socket;
this.worker = worker;
config = new DefaultNioSocketChannelConfig(socket.socket());
// TODO Move the state variable to AbstractChannel so that we don't need
// to add many listeners.
getCloseFuture().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
state = ST_CLOSED;
}
});
}
public NioSocketChannelConfig getConfig() {
@ -142,7 +151,6 @@ class NioSocketChannel extends AbstractChannel
@Override
protected boolean setClosed() {
state = ST_CLOSED;
return super.setClosed();
}