use of io.netty.channel.DefaultEventLoop in project netty by netty.
the class FixedChannelPoolMapDeadlockTest method testDeadlockOnAcquire.
@Test
public void testDeadlockOnAcquire() throws Exception {
final EventLoop threadA1 = new DefaultEventLoop();
final Bootstrap bootstrapA1 = new Bootstrap().channel(LocalChannel.class).group(threadA1).localAddress(new LocalAddress("A1"));
final EventLoop threadA2 = new DefaultEventLoop();
final Bootstrap bootstrapA2 = new Bootstrap().channel(LocalChannel.class).group(threadA2).localAddress(new LocalAddress("A2"));
final EventLoop threadB1 = new DefaultEventLoop();
final Bootstrap bootstrapB1 = new Bootstrap().channel(LocalChannel.class).group(threadB1).localAddress(new LocalAddress("B1"));
final EventLoop threadB2 = new DefaultEventLoop();
final Bootstrap bootstrapB2 = new Bootstrap().channel(LocalChannel.class).group(threadB2).localAddress(new LocalAddress("B2"));
final FixedChannelPool poolA1 = new FixedChannelPool(bootstrapA1, NOOP_HANDLER, 1);
final FixedChannelPool poolA2 = new FixedChannelPool(bootstrapB2, NOOP_HANDLER, 1);
final FixedChannelPool poolB1 = new FixedChannelPool(bootstrapB1, NOOP_HANDLER, 1);
final FixedChannelPool poolB2 = new FixedChannelPool(bootstrapA2, NOOP_HANDLER, 1);
// Synchronize threads on these barriers to ensure order of execution, first wait until each thread is inside
// the newPool callback, then hold the two threads that should lose the match until the first two returns, then
// release them to test if they deadlock when trying to release their pools on each other's threads.
final CyclicBarrier arrivalBarrier = new CyclicBarrier(4);
final CyclicBarrier releaseBarrier = new CyclicBarrier(3);
final AbstractChannelPoolMap<String, FixedChannelPool> channelPoolMap = new AbstractChannelPoolMap<String, FixedChannelPool>() {
@Override
protected FixedChannelPool newPool(String key) {
if ("A".equals(key)) {
if (threadA1.inEventLoop()) {
// Thread A1 gets pool A with thread A1
await(arrivalBarrier);
return poolA1;
} else if (threadA2.inEventLoop()) {
// Thread A2 gets pool A with thread B2, but only after A1 won
await(arrivalBarrier);
await(releaseBarrier);
return poolA2;
}
} else if ("B".equals(key)) {
if (threadB1.inEventLoop()) {
// Thread B1 gets pool with thread B1
await(arrivalBarrier);
return poolB1;
} else if (threadB2.inEventLoop()) {
// Thread B2 gets pool with thread A2
await(arrivalBarrier);
await(releaseBarrier);
return poolB2;
}
}
throw new AssertionError("Unexpected key=" + key + " or thread=" + Thread.currentThread().getName());
}
};
// Thread A1 calls ChannelPoolMap.get(A)
// Thread A2 calls ChannelPoolMap.get(A)
// Thread B1 calls ChannelPoolMap.get(B)
// Thread B2 calls ChannelPoolMap.get(B)
Future<FixedChannelPool> futureA1 = threadA1.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("A");
}
});
Future<FixedChannelPool> futureA2 = threadA2.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("A");
}
});
Future<FixedChannelPool> futureB1 = threadB1.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("B");
}
});
Future<FixedChannelPool> futureB2 = threadB2.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("B");
}
});
// These should always succeed and return with new pools
try {
assertSame(poolA1, futureA1.get(1, TimeUnit.SECONDS));
assertSame(poolB1, futureB1.get(1, TimeUnit.SECONDS));
} catch (Exception e) {
shutdown(threadA1, threadA2, threadB1, threadB2);
throw e;
}
// Now release the other two threads which at this point lost the race and will try to clean up the acquired
// pools. The expected scenario is that both pools close, in case of a deadlock they will hang.
await(releaseBarrier);
// If the close is not blocking, then the previously created pools will be returned
try {
assertSame(poolA1, futureA2.get(1, TimeUnit.SECONDS));
assertSame(poolB1, futureB2.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
// Fail the test on timeout to distinguish from other errors
throw new AssertionError(e);
} finally {
poolA1.close();
poolA2.close();
poolB1.close();
poolB2.close();
channelPoolMap.close();
shutdown(threadA1, threadA2, threadB1, threadB2);
}
}
use of io.netty.channel.DefaultEventLoop in project rocketmq-externals by apache.
the class MqttIdleHandlerTest method setup.
@Before
public void setup() throws IllegalAccessException {
idleHandler = new MqttIdleHandler(1);
ctx = Mockito.mock(ChannelHandlerContext.class);
// channel = Mockito.spy(new EmbeddedChannel());
// channel.attr(ChannelConfiguration.CHANNEL_IDLE_TIME_ATTRIBUTE_KEY).set(5);
channel = Mockito.mock(Channel.class);
state = (AtomicReference<MqttIdleHandler.State>) FieldUtils.getField(MqttIdleHandler.class, "state", true).get(idleHandler);
loop = new DefaultEventLoop();
Mockito.when(ctx.channel()).thenReturn(channel);
Mockito.when(ctx.executor()).thenReturn(loop);
Mockito.when(ctx.fireChannelRead(Mockito.any())).then(new Answer() {
@Override
public Object answer(InvocationOnMock mock) throws Throwable {
return null;
}
});
Mockito.when(ctx.channel().isOpen()).thenReturn(true);
Mockito.when(ctx.fireUserEventTriggered(Mockito.any(IdleStateEvent.class))).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock mock) throws Throwable {
loop.shutdownGracefully();
return null;
}
});
}
use of io.netty.channel.DefaultEventLoop in project netty by netty.
the class FixedChannelPoolMapDeadlockTest method testDeadlockOnRemove.
@Test
public void testDeadlockOnRemove() throws Exception {
final EventLoop thread1 = new DefaultEventLoop();
final Bootstrap bootstrap1 = new Bootstrap().channel(LocalChannel.class).group(thread1).localAddress(new LocalAddress("#1"));
final EventLoop thread2 = new DefaultEventLoop();
final Bootstrap bootstrap2 = new Bootstrap().channel(LocalChannel.class).group(thread2).localAddress(new LocalAddress("#2"));
// pool1 runs on thread2, pool2 runs on thread1
final FixedChannelPool pool1 = new FixedChannelPool(bootstrap2, NOOP_HANDLER, 1);
final FixedChannelPool pool2 = new FixedChannelPool(bootstrap1, NOOP_HANDLER, 1);
final AbstractChannelPoolMap<String, FixedChannelPool> channelPoolMap = new AbstractChannelPoolMap<String, FixedChannelPool>() {
@Override
protected FixedChannelPool newPool(String key) {
if ("#1".equals(key)) {
return pool1;
} else if ("#2".equals(key)) {
return pool2;
} else {
throw new AssertionError("Unexpected key=" + key);
}
}
};
assertSame(pool1, channelPoolMap.get("#1"));
assertSame(pool2, channelPoolMap.get("#2"));
// thread1 tries to remove pool1 which is running on thread2
// thread2 tries to remove pool2 which is running on thread1
final CyclicBarrier barrier = new CyclicBarrier(2);
Future<?> future1 = thread1.submit(new Runnable() {
@Override
public void run() {
await(barrier);
channelPoolMap.remove("#1");
}
});
Future<?> future2 = thread2.submit(new Runnable() {
@Override
public void run() {
await(barrier);
channelPoolMap.remove("#2");
}
});
// A blocking close on remove will cause a deadlock here and the test will time out
try {
future1.get(1, TimeUnit.SECONDS);
future2.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// Fail the test on timeout to distinguish from other errors
throw new AssertionError(e);
} finally {
pool1.close();
pool2.close();
channelPoolMap.close();
shutdown(thread1, thread2);
}
}
use of io.netty.channel.DefaultEventLoop in project netty by netty.
the class Http2StreamChannelBootstrapTest method testStreamIsNotCreatedIfParentConnectionIsClosedConcurrently.
@Test
public void testStreamIsNotCreatedIfParentConnectionIsClosedConcurrently() throws Exception {
EventLoopGroup group = null;
Channel serverChannel = null;
Channel clientChannel = null;
try {
final CountDownLatch serverChannelLatch = new CountDownLatch(1);
group = new DefaultEventLoop();
LocalAddress serverAddress = new LocalAddress(getClass().getName());
ServerBootstrap sb = new ServerBootstrap().channel(LocalServerChannel.class).group(group).childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
serverConnectedChannel = ch;
ch.pipeline().addLast(forServer().build(), newMultiplexedHandler());
serverChannelLatch.countDown();
}
});
serverChannel = sb.bind(serverAddress).sync().channel();
Bootstrap cb = new Bootstrap().channel(LocalChannel.class).group(group).handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(forClient().build(), newMultiplexedHandler());
}
});
clientChannel = cb.connect(serverAddress).sync().channel();
assertTrue(serverChannelLatch.await(3, SECONDS));
final CountDownLatch closeLatch = new CountDownLatch(1);
final Channel clientChannelToClose = clientChannel;
group.execute(new Runnable() {
@Override
public void run() {
try {
closeLatch.await();
clientChannelToClose.close().syncUninterruptibly();
} catch (InterruptedException e) {
logger.error(e);
}
}
});
Http2StreamChannelBootstrap bootstrap = new Http2StreamChannelBootstrap(clientChannel);
final Promise<Http2StreamChannel> promise = clientChannel.eventLoop().newPromise();
bootstrap.open(promise);
assertThat(promise.isDone(), is(false));
closeLatch.countDown();
ExecutionException exception = assertThrows(ExecutionException.class, new Executable() {
@Override
public void execute() throws Throwable {
promise.get(3, SECONDS);
}
});
assertThat(exception.getCause(), IsInstanceOf.<Throwable>instanceOf(ClosedChannelException.class));
} finally {
safeClose(clientChannel);
safeClose(serverConnectedChannel);
safeClose(serverChannel);
if (group != null) {
group.shutdownGracefully(0, 3, SECONDS);
}
}
}
use of io.netty.channel.DefaultEventLoop in project zuul by Netflix.
the class DefaultClientChannelManagerTest method updateServerRefOnEmptyDiscoveryResult.
@Test
public void updateServerRefOnEmptyDiscoveryResult() {
OriginName originName = OriginName.fromVip("vip", "test");
final DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl();
final DynamicServerResolver resolver = mock(DynamicServerResolver.class);
when(resolver.resolve(any())).thenReturn(DiscoveryResult.EMPTY);
final DefaultClientChannelManager clientChannelManager = new DefaultClientChannelManager(originName, clientConfig, resolver, new DefaultRegistry());
final AtomicReference<DiscoveryResult> serverRef = new AtomicReference<>();
final Promise<PooledConnection> promise = clientChannelManager.acquire(new DefaultEventLoop(), null, CurrentPassport.create(), serverRef, new AtomicReference<>());
Truth.assertThat(promise.isSuccess()).isFalse();
Truth.assertThat(serverRef.get()).isSameInstanceAs(DiscoveryResult.EMPTY);
}
Aggregations