From f33f9612a7c09e464a01eb9c0cf50ced909c67fe Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Thu, 14 Dec 2017 14:37:41 -0700 Subject: [PATCH] Remove potential nio selector leak (#27825) When an ESSelector is created an underlying nio selector is opened. This selector is closed by the event loop after close has been signalled by another thread. However, there is a possibility that an ESSelector is created and some exception in the startup process prevents it from ever being started (however, close will still be called). The allows the selector to leak. This commit addresses this issue by having the signalling thread close the selector if the event loop is not running when close is signalled. --- .../java/org/elasticsearch/transport/nio/ESSelector.java | 5 ++++- .../org/elasticsearch/transport/nio/ESSelectorTests.java | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java index 667107f7b3e..91e308a33b5 100644 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java +++ b/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java @@ -177,8 +177,11 @@ public abstract class ESSelector implements Closeable { try { exitedLoop.await(); } catch (InterruptedException e) { - eventHandler.uncaughtException(e); + Thread.currentThread().interrupt(); + throw new IllegalStateException("Thread was interrupted while waiting for selector to close", e); } + } else if (selector.isOpen()) { + selector.close(); } } } diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java index 69c2c00489d..6459447c1a8 100644 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java +++ b/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java @@ -81,6 +81,12 @@ public class ESSelectorTests extends ESTestCase { verify(handler).selectException(ioException); } + public void testSelectorClosedIfOpenAndEventLoopNotRunning() throws IOException { + when(rawSelector.isOpen()).thenReturn(true); + selector.close(); + verify(rawSelector).close(); + } + private static class TestSelector extends ESSelector { TestSelector(EventHandler eventHandler, Selector selector) throws IOException {