Add a unit test that reproduces the dead lock described in #1175

- The offending test case is annotated with `@Ignore`
- Also fixed a bug where channel initialization failure swallows the original cause of initialization failure
This commit is contained in:
Trustin Lee 2013-03-21 18:43:03 +09:00
parent a980638190
commit 2aa0bf73dc
2 changed files with 95 additions and 1 deletions

View File

@ -81,7 +81,11 @@ public final class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
try {
init(channel);
} catch (Throwable t) {
channel.close();
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
return channel.newFailedFuture(t);
}

View File

@ -0,0 +1,90 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.bootstrap;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandler;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.local.LocalAddress;
import io.netty.channel.local.LocalChannel;
import io.netty.channel.local.LocalEventLoopGroup;
import io.netty.util.concurrent.Future;
import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class BootstrapTest {
@Test(timeout = 10000)
@Ignore
public void testInitializationDeadLock() throws Exception {
EventLoopGroup groupA = new LocalEventLoopGroup(1);
EventLoopGroup groupB = new LocalEventLoopGroup(1);
try {
ChannelInboundMessageHandler<Object> dummyHandler = new DummyHandler();
final Bootstrap bootstrapA = new Bootstrap();
bootstrapA.group(groupA);
bootstrapA.channel(LocalChannel.class);
bootstrapA.handler(dummyHandler);
final Bootstrap bootstrapB = new Bootstrap();
bootstrapB.group(groupB);
bootstrapB.channel(LocalChannel.class);
bootstrapB.handler(dummyHandler);
List<Future<?>> bindFutures = new ArrayList<Future<?>>();
// Try to bind from each other.
for (int i = 0; i < 1024; i ++) {
bindFutures.add(groupA.next().submit(new Runnable() {
@Override
public void run() {
bootstrapB.bind(LocalAddress.ANY);
}
}));
bindFutures.add(groupB.next().submit(new Runnable() {
@Override
public void run() {
bootstrapA.bind(LocalAddress.ANY);
}
}));
}
for (Future<?> f: bindFutures) {
f.sync();
}
} finally {
groupA.shutdown();
groupB.shutdown();
}
}
@Sharable
private static final class DummyHandler extends ChannelInboundMessageHandlerAdapter<Object> {
@Override
public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
// NOOP
}
}
}