diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java b/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java index deade5e8d..dd7b30e2b 100644 --- a/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java @@ -329,16 +329,39 @@ abstract class AbstractChannelReplicator implements Closeable { final Thread thread = new Thread(new Runnable() { public void run() { + SelectableChannel socketChannel = null; try { if (reconnectionInterval > 0) Thread.sleep(reconnectionInterval); - SelectableChannel socketChannel = doConnect(); - closeables.add(socketChannel); + socketChannel = doConnect(); + + try { + closeables.add(socketChannel); + } catch (IllegalStateException e) { + + // close could have be called from another thread, while we were in Thread.sleep() + // which would cause a IllegalStateException + closeQuietly(socketChannel); + return; + } + AbstractConnector.this.socketChannel = socketChannel; + } catch (Exception e) { - LOG.error("", e); + closeQuietly(socketChannel); + LOG.debug("", e); + } + } + + private void closeQuietly(SelectableChannel socketChannel) { + if (socketChannel == null) + return; + try { + socketChannel.close(); + } catch (Exception e1) { + // do nothing } } }); @@ -346,6 +369,8 @@ abstract class AbstractChannelReplicator implements Closeable { thread.setName(name); thread.setDaemon(true); thread.start(); + + } public void setSuccessfullyConnected() { diff --git a/src/main/java/net/openhft/chronicle/map/CloseablesManager.java b/src/main/java/net/openhft/chronicle/map/CloseablesManager.java index e4a655530..16eefb0c3 100644 --- a/src/main/java/net/openhft/chronicle/map/CloseablesManager.java +++ b/src/main/java/net/openhft/chronicle/map/CloseablesManager.java @@ -29,7 +29,7 @@ final class CloseablesManager implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(CloseablesManager.class.getName()); private boolean isClosed = false; - private List closeables = new ArrayList(); + private final List closeables = new ArrayList<>(); private void checkState() { if (isClosed) @@ -84,4 +84,8 @@ final class CloseablesManager implements Closeable { // do nothing } } + + boolean isClosed() { + return isClosed; + } } diff --git a/src/test/java/net/openhft/chronicle/map/Issue42.java b/src/test/java/net/openhft/chronicle/map/Issue42.java index e9d03840a..f0f6ea530 100644 --- a/src/test/java/net/openhft/chronicle/map/Issue42.java +++ b/src/test/java/net/openhft/chronicle/map/Issue42.java @@ -9,8 +9,20 @@ import static net.openhft.chronicle.map.Alignment.NO_ALIGNMENT; import static net.openhft.chronicle.map.Builder.getPersistenceFile; public class Issue42 { + + private static String OS = System.getProperty("os.name").toLowerCase(); + + public static boolean isWindows() { + return (OS.indexOf("win") >= 0); + } + + @Test public void crashJVMWindowsTest() throws IOException { + + if (!isWindows()) + return; + final ChronicleMap map = ChronicleMapBuilder .of(CharSequence.class, CharSequence.class) .entryAndValueAlignment(NO_ALIGNMENT)