Browse Source

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

EPC-fixes
catbref 2 years ago
parent
commit
3e622f7185
  1. 51
      src/main/java/org/qortal/network/Network.java

51
src/main/java/org/qortal/network/Network.java

@ -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;
} }
} }

Loading…
Cancel
Save