[#2400] Not close LocalChannel during deregister() to allow register to other EventLoop

Motivation:
At the moment it is not possible to deregister a LocalChannel from its EventLoop and register it to another one as the LocalChannel is closed during the deregister.

Modification:
Not close the LocalChannel during dergister

Result:
It is now possible to deregister a LocalChannel and register it to another EventLoop
This commit is contained in:
Norman Maurer 2014-04-20 19:47:48 +02:00
parent b5ab5150be
commit 7ae40ace32
2 changed files with 40 additions and 4 deletions

View File

@ -155,7 +155,12 @@ public class LocalChannel extends AbstractChannel {
@Override
protected void doRegister() throws Exception {
if (peer != null) {
// Check if both peer and parent are non-null because this channel was created by a LocalServerChannel.
// This is needed as a peer may not be null also if a LocalChannel was connected before and
// deregistered / registered later again.
//
// See https://github.com/netty/netty/issues/2400
if (peer != null && parent() != null) {
// Store the peer in a local variable as it may be set to null if doClose() is called.
// Because of this we also set registerInProgress to true as we check for this in doClose() and make sure
// we delay the fireChannelInactive() to be fired after the fireChannelActive() and so keep the correct
@ -237,9 +242,7 @@ public class LocalChannel extends AbstractChannel {
@Override
protected void doDeregister() throws Exception {
if (isOpen()) {
unsafe().close(unsafe().voidPromise());
}
// Just remove the shutdownHook as this Channel may be closed later or registered to another EventLoop
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
}

View File

@ -248,6 +248,39 @@ public class LocalChannelTest {
}
}
@Test
public void testReRegister() {
EventLoopGroup group1 = new LocalEventLoopGroup();
EventLoopGroup group2 = new LocalEventLoopGroup();
LocalAddress addr = new LocalAddress(LOCAL_ADDR_ID);
Bootstrap cb = new Bootstrap();
ServerBootstrap sb = new ServerBootstrap();
cb.group(group1)
.channel(LocalChannel.class)
.handler(new TestHandler());
sb.group(group2)
.channel(LocalServerChannel.class)
.childHandler(new ChannelInitializer<LocalChannel>() {
@Override
public void initChannel(LocalChannel ch) throws Exception {
ch.pipeline().addLast(new TestHandler());
}
});
// Start server
final Channel sc = sb.bind(addr).syncUninterruptibly().channel();
// Connect to the server
final Channel cc = cb.connect(addr).syncUninterruptibly().channel();
cc.deregister().syncUninterruptibly();
// Change event loop group.
group2.register(cc).syncUninterruptibly();
cc.close().syncUninterruptibly();
sc.close().syncUninterruptibly();
}
static class TestHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {