[#2644] Correctly release buffer when exception happens during send DatagramPacket or SctpMessage

Motivation:

When an exception is thrown during try to send DatagramPacket or SctpMessage a buffer may leak.

Modification:

Correctly handle allocated buffers in case of exception

Result:

No more leaks
This commit is contained in:
Norman Maurer 2014-07-08 20:15:33 +02:00
parent 26c20c91bd
commit 21aa3d8997
2 changed files with 39 additions and 30 deletions

View File

@ -316,14 +316,18 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett
data = alloc.directBuffer(dataLen).writeBytes(data); data = alloc.directBuffer(dataLen).writeBytes(data);
nioData = data.nioBuffer(); nioData = data.nioBuffer();
} }
final MessageInfo mi = MessageInfo.createOutgoing(association(), null, packet.streamIdentifier()); final MessageInfo mi = MessageInfo.createOutgoing(association(), null, packet.streamIdentifier());
mi.payloadProtocolID(packet.protocolIdentifier()); mi.payloadProtocolID(packet.protocolIdentifier());
mi.streamNumber(packet.streamIdentifier()); mi.streamNumber(packet.streamIdentifier());
boolean done = false;
try {
final int writtenBytes = javaChannel().send(nioData, mi); final int writtenBytes = javaChannel().send(nioData, mi);
done = writtenBytes > 0;
boolean done = writtenBytes > 0; return done;
} finally {
// Handle this in the finally block to make sure we release the old buffer in all cases
// See https://github.com/netty/netty/issues/2644
if (needsCopy) { if (needsCopy) {
if (!done) { if (!done) {
in.current(new SctpMessage(mi, data)); in.current(new SctpMessage(mi, data));
@ -331,7 +335,7 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett
in.current(data); in.current(data);
} }
} }
return done; }
} }
@Override @Override

View File

@ -300,17 +300,22 @@ public final class NioDatagramChannel
nioData = data.nioBuffer(); nioData = data.nioBuffer();
} }
boolean done = false;
try {
final int writtenBytes; final int writtenBytes;
if (remoteAddress != null) { if (remoteAddress != null) {
writtenBytes = javaChannel().send(nioData, remoteAddress); writtenBytes = javaChannel().send(nioData, remoteAddress);
} else { } else {
writtenBytes = javaChannel().write(nioData); writtenBytes = javaChannel().write(nioData);
} }
done = writtenBytes > 0;
boolean done = writtenBytes > 0; return done;
} finally {
// Handle this in the finally block to make sure we release the old buffer in all cases
// See https://github.com/netty/netty/issues/2644
if (needsCopy) { if (needsCopy) {
// This means we have allocated a new buffer and need to store it back so we not need to allocate it again // This means we have allocated a new buffer and need to store it back so we not need to allocate it
// later // later again
if (remoteAddress == null) { if (remoteAddress == null) {
// remoteAddress is null which means we can handle it as ByteBuf directly // remoteAddress is null which means we can handle it as ByteBuf directly
in.current(data); in.current(data);
@ -319,12 +324,12 @@ public final class NioDatagramChannel
// store it back with all the needed informations // store it back with all the needed informations
in.current(new DefaultAddressedEnvelope<ByteBuf, SocketAddress>(data, remoteAddress)); in.current(new DefaultAddressedEnvelope<ByteBuf, SocketAddress>(data, remoteAddress));
} else { } else {
// Just store back the new create buffer so it is cleaned up once in.remove() is called. // Just store back the new created buffer so it is cleaned up once in.remove() is called.
in.current(data); in.current(data);
} }
} }
} }
return done; }
} }
@Override @Override