From 3e622f718586f4fffd0d8017498a73aced00709a Mon Sep 17 00:00:00 2001 From: catbref Date: Mon, 18 Apr 2022 14:33:05 +0100 Subject: [PATCH] EPC-fixes: catch CancelledKeyExceptions thrown in short window between nextSelectionKey.isValid() and nextSelectionKey.isXXXable() calls --- src/main/java/org/qortal/network/Network.java | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/qortal/network/Network.java b/src/main/java/org/qortal/network/Network.java index 725d336f..9c797901 100644 --- a/src/main/java/org/qortal/network/Network.java +++ b/src/main/java/org/qortal/network/Network.java @@ -590,32 +590,41 @@ public class Network { SelectableChannel socketChannel = nextSelectionKey.channel(); - if (nextSelectionKey.isReadable()) { - clearInterestOps(nextSelectionKey, SelectionKey.OP_READ); - Peer peer = getPeerFromChannel((SocketChannel) socketChannel); - if (peer == null) - return null; + try { + if (nextSelectionKey.isReadable()) { + clearInterestOps(nextSelectionKey, SelectionKey.OP_READ); + Peer peer = getPeerFromChannel((SocketChannel) socketChannel); + if (peer == null) + return null; - return new ChannelReadTask((SocketChannel) socketChannel, peer); - } + return new ChannelReadTask((SocketChannel) socketChannel, peer); + } - if (nextSelectionKey.isWritable()) { - clearInterestOps(nextSelectionKey, SelectionKey.OP_WRITE); - Peer peer = getPeerFromChannel((SocketChannel) socketChannel); - if (peer == null) - return null; + if (nextSelectionKey.isWritable()) { + clearInterestOps(nextSelectionKey, SelectionKey.OP_WRITE); + Peer peer = getPeerFromChannel((SocketChannel) socketChannel); + if (peer == null) + return null; - // Any thread that queues a message to send can set OP_WRITE, - // but we only allow one pending/active ChannelWriteTask per Peer - if (!channelsPendingWrite.add(socketChannel)) - return null; + // Any thread that queues a message to send can set OP_WRITE, + // but we only allow one pending/active ChannelWriteTask per Peer + if (!channelsPendingWrite.add(socketChannel)) + return null; - return new ChannelWriteTask((SocketChannel) socketChannel, peer); - } + return new ChannelWriteTask((SocketChannel) socketChannel, peer); + } - if (nextSelectionKey.isAcceptable()) { - clearInterestOps(nextSelectionKey, SelectionKey.OP_ACCEPT); - return new ChannelAcceptTask((ServerSocketChannel) socketChannel); + if (nextSelectionKey.isAcceptable()) { + clearInterestOps(nextSelectionKey, SelectionKey.OP_ACCEPT); + return new ChannelAcceptTask((ServerSocketChannel) socketChannel); + } + } catch (CancelledKeyException e) { + /* + * Sometimes nextSelectionKey is cancelled / becomes invalid between the isValid() test at line 586 + * and later calls to isReadable() / isWritable() / isAcceptable() which themselves call isValid()! + * Those isXXXable() calls could throw CancelledKeyException, so we catch it here and return null. + */ + return null; } }