3
0
mirror of https://github.com/Qortal/qortal.git synced 2025-02-12 10:15:49 +00:00

EPC-fixes: catch CancelledKeyExceptions thrown in short window between nextSelectionKey.isValid() and nextSelectionKey.isXXXable() calls

This commit is contained in:
catbref 2022-04-18 14:33:05 +01:00
parent 68412b49a1
commit 3e622f7185

View File

@ -590,32 +590,41 @@ public class Network {
SelectableChannel socketChannel = nextSelectionKey.channel(); SelectableChannel socketChannel = nextSelectionKey.channel();
if (nextSelectionKey.isReadable()) { try {
clearInterestOps(nextSelectionKey, SelectionKey.OP_READ); if (nextSelectionKey.isReadable()) {
Peer peer = getPeerFromChannel((SocketChannel) socketChannel); clearInterestOps(nextSelectionKey, SelectionKey.OP_READ);
if (peer == null) Peer peer = getPeerFromChannel((SocketChannel) socketChannel);
return null; if (peer == null)
return null;
return new ChannelReadTask((SocketChannel) socketChannel, peer); return new ChannelReadTask((SocketChannel) socketChannel, peer);
} }
if (nextSelectionKey.isWritable()) { if (nextSelectionKey.isWritable()) {
clearInterestOps(nextSelectionKey, SelectionKey.OP_WRITE); clearInterestOps(nextSelectionKey, SelectionKey.OP_WRITE);
Peer peer = getPeerFromChannel((SocketChannel) socketChannel); Peer peer = getPeerFromChannel((SocketChannel) socketChannel);
if (peer == null) if (peer == null)
return null; return null;
// Any thread that queues a message to send can set OP_WRITE, // Any thread that queues a message to send can set OP_WRITE,
// but we only allow one pending/active ChannelWriteTask per Peer // but we only allow one pending/active ChannelWriteTask per Peer
if (!channelsPendingWrite.add(socketChannel)) if (!channelsPendingWrite.add(socketChannel))
return null; return null;
return new ChannelWriteTask((SocketChannel) socketChannel, peer); return new ChannelWriteTask((SocketChannel) socketChannel, peer);
} }
if (nextSelectionKey.isAcceptable()) { if (nextSelectionKey.isAcceptable()) {
clearInterestOps(nextSelectionKey, SelectionKey.OP_ACCEPT); clearInterestOps(nextSelectionKey, SelectionKey.OP_ACCEPT);
return new ChannelAcceptTask((ServerSocketChannel) socketChannel); 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;
} }
} }