From 564d5833cc8caed3986e29119157177bef8ef6cc Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 5 Dec 2018 15:31:21 +0100 Subject: [PATCH] =?UTF-8?q?NioEventLoop.register(...)=20should=20offload?= =?UTF-8?q?=20to=20the=20EventLoop=20if=20not=20alr=E2=80=A6=20(#8612)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Motivation: java.nio.channels.spi.AbstractSelectableChannel.register(...) need to obtain multiple locks during execution which may produce a long wait time if we currently select. This lead to multiple CI failures in the past. Modifications: Ensure the register call takes place on the EventLoop. Result: No more flacky CI test timeouts. --- .../io/netty/channel/nio/NioEventLoop.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java b/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java index 539ac81d37..16695c8f7e 100644 --- a/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java +++ b/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java @@ -33,8 +33,9 @@ import java.io.IOException; import java.lang.reflect.Field; import java.nio.channels.CancelledKeyException; import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; import java.nio.channels.Selector; +import java.nio.channels.SelectionKey; + import java.nio.channels.spi.SelectorProvider; import java.security.AccessController; import java.security.PrivilegedAction; @@ -293,6 +294,26 @@ public final class NioEventLoop extends SingleThreadEventLoop { throw new IllegalStateException("event loop shut down"); } + if (inEventLoop()) { + register0(ch, interestOps, task); + } else { + try { + // Offload to the EventLoop as otherwise java.nio.channels.spi.AbstractSelectableChannel.register + // may block for a long time while trying to obtain an internal lock that may be hold while selecting. + submit(new Runnable() { + @Override + public void run() { + register0(ch, interestOps, task); + } + }).sync(); + } catch (InterruptedException ignore) { + // Even if interrupted we did schedule it so just mark the Thread as interrupted. + Thread.currentThread().interrupt(); + } + } + } + + private void register0(SelectableChannel ch, int interestOps, NioTask task) { try { ch.register(unwrappedSelector, interestOps, task); } catch (Exception e) {