Search in sources :

Example 1 with DefaultEventLoop

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);
    }
}
Also used : LocalAddress(io.netty.channel.local.LocalAddress) DefaultEventLoop(io.netty.channel.DefaultEventLoop) TimeoutException(java.util.concurrent.TimeoutException) CyclicBarrier(java.util.concurrent.CyclicBarrier) DefaultEventLoop(io.netty.channel.DefaultEventLoop) EventLoop(io.netty.channel.EventLoop) Bootstrap(io.netty.bootstrap.Bootstrap) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.jupiter.api.Test)

Example 2 with DefaultEventLoop

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;
        }
    });
}
Also used : IdleStateEvent(io.netty.handler.timeout.IdleStateEvent) Answer(org.mockito.stubbing.Answer) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Channel(io.netty.channel.Channel) DefaultEventLoop(io.netty.channel.DefaultEventLoop) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) Before(org.junit.Before)

Example 3 with DefaultEventLoop

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);
    }
}
Also used : LocalAddress(io.netty.channel.local.LocalAddress) DefaultEventLoop(io.netty.channel.DefaultEventLoop) CyclicBarrier(java.util.concurrent.CyclicBarrier) DefaultEventLoop(io.netty.channel.DefaultEventLoop) EventLoop(io.netty.channel.EventLoop) Bootstrap(io.netty.bootstrap.Bootstrap) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.jupiter.api.Test)

Example 4 with DefaultEventLoop

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);
        }
    }
}
Also used : ClosedChannelException(java.nio.channels.ClosedChannelException) LocalAddress(io.netty.channel.local.LocalAddress) LocalServerChannel(io.netty.channel.local.LocalServerChannel) LocalChannel(io.netty.channel.local.LocalChannel) Channel(io.netty.channel.Channel) DefaultEventLoop(io.netty.channel.DefaultEventLoop) CountDownLatch(java.util.concurrent.CountDownLatch) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) EventLoopGroup(io.netty.channel.EventLoopGroup) Bootstrap(io.netty.bootstrap.Bootstrap) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) ExecutionException(java.util.concurrent.ExecutionException) Executable(org.junit.jupiter.api.function.Executable) Test(org.junit.jupiter.api.Test)

Example 5 with DefaultEventLoop

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);
}
Also used : OriginName(com.netflix.zuul.origins.OriginName) DiscoveryResult(com.netflix.zuul.discovery.DiscoveryResult) DefaultRegistry(com.netflix.spectator.api.DefaultRegistry) DefaultEventLoop(io.netty.channel.DefaultEventLoop) DynamicServerResolver(com.netflix.zuul.discovery.DynamicServerResolver) AtomicReference(java.util.concurrent.atomic.AtomicReference) DefaultClientConfigImpl(com.netflix.client.config.DefaultClientConfigImpl) Test(org.junit.Test)

Aggregations

DefaultEventLoop (io.netty.channel.DefaultEventLoop)7 Bootstrap (io.netty.bootstrap.Bootstrap)3 LocalAddress (io.netty.channel.local.LocalAddress)3 Test (org.junit.jupiter.api.Test)3 DefaultClientConfigImpl (com.netflix.client.config.DefaultClientConfigImpl)2 DefaultRegistry (com.netflix.spectator.api.DefaultRegistry)2 DiscoveryResult (com.netflix.zuul.discovery.DiscoveryResult)2 DynamicServerResolver (com.netflix.zuul.discovery.DynamicServerResolver)2 OriginName (com.netflix.zuul.origins.OriginName)2 ServerBootstrap (io.netty.bootstrap.ServerBootstrap)2 Channel (io.netty.channel.Channel)2 EventLoop (io.netty.channel.EventLoop)2 CyclicBarrier (java.util.concurrent.CyclicBarrier)2 TimeoutException (java.util.concurrent.TimeoutException)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Test (org.junit.Test)2 Event (com.blade.event.Event)1 InstanceInfo (com.netflix.appinfo.InstanceInfo)1 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)1 EventLoopGroup (io.netty.channel.EventLoopGroup)1