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) {