diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java index b733ce4edb..25ef612fc9 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java @@ -256,20 +256,27 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements break; } - boolean done = false; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { - if (doWriteMessage(msg)) { - done = true; + try { + boolean done = false; + for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { + if (doWriteMessage(msg)) { + done = true; + break; + } + } + + if (done) { + in.remove(); + } else { + // Did not write all messages. + setEpollOut(); break; } - } - - if (done) { - in.remove(); - } else { - // Did not write all messages. - setEpollOut(); - break; + } catch (IOException e) { + // Continue on write error as a DatagramChannel can write to multiple remote peers + // + // See https://github.com/netty/netty/issues/2665 + in.remove(e); } } } diff --git a/transport/src/main/java/io/netty/channel/nio/AbstractNioMessageChannel.java b/transport/src/main/java/io/netty/channel/nio/AbstractNioMessageChannel.java index c9e537431a..8a9f16a0d7 100644 --- a/transport/src/main/java/io/netty/channel/nio/AbstractNioMessageChannel.java +++ b/transport/src/main/java/io/netty/channel/nio/AbstractNioMessageChannel.java @@ -138,27 +138,41 @@ public abstract class AbstractNioMessageChannel extends AbstractNioChannel { } break; } + try { + boolean done = false; + for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { + if (doWriteMessage(msg, in)) { + done = true; + break; + } + } - boolean done = false; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) { - if (doWriteMessage(msg, in)) { - done = true; + if (done) { + in.remove(); + } else { + // Did not write all messages. + if ((interestOps & SelectionKey.OP_WRITE) == 0) { + key.interestOps(interestOps | SelectionKey.OP_WRITE); + } break; } - } - - if (done) { - in.remove(); - } else { - // Did not write all messages. - if ((interestOps & SelectionKey.OP_WRITE) == 0) { - key.interestOps(interestOps | SelectionKey.OP_WRITE); + } catch (IOException e) { + if (continueOnWriteError()) { + in.remove(e); + } else { + throw e; } - break; } } } + /** + * Returns {@code true} if we should continue the write loop on a write error. + */ + protected boolean continueOnWriteError() { + return false; + } + /** * Read messages into the given array and return the amount which was read. */ diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java index 93f7721976..9ef4717209 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java @@ -291,10 +291,17 @@ public final class NioDatagramChannel } else { writtenBytes = javaChannel().write(nioData); } - return writtenBytes > 0; } + @Override + protected boolean continueOnWriteError() { + // Continue on write error as a DatagramChannel can write to multiple remote peers + // + // See https://github.com/netty/netty/issues/2665 + return true; + } + @Override public InetSocketAddress localAddress() { return (InetSocketAddress) super.localAddress(); diff --git a/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java index ca873486b2..eeab486184 100644 --- a/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java @@ -276,8 +276,15 @@ public class OioDatagramChannel extends AbstractOioMessageChannel data.getBytes(data.readerIndex(), tmp); tmpPacket.setData(tmp); } - socket.send(tmpPacket); - in.remove(); + try { + socket.send(tmpPacket); + in.remove(); + } catch (IOException e) { + // Continue on write error as a DatagramChannel can write to multiple remote peers + // + // See https://github.com/netty/netty/issues/2665 + in.remove(e); + } } }