Close the file in case of an IOException in AbstractMemoryHttpData.renameTo. (#10163)
Motivation: An `IOException` may be thrown from `FileChannel.write` or `FileChannel.force`, and cause the fd leak. Modification: Close the file in a finally block. Result: Avoid fd leak.
This commit is contained in:
parent
363c4ecc7f
commit
3ebf3d7705
@ -237,24 +237,29 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData {
|
||||
return true;
|
||||
}
|
||||
int length = byteBuf.readableBytes();
|
||||
RandomAccessFile accessFile = new RandomAccessFile(dest, "rw");
|
||||
FileChannel fileChannel = accessFile.getChannel();
|
||||
int written = 0;
|
||||
if (byteBuf.nioBufferCount() == 1) {
|
||||
ByteBuffer byteBuffer = byteBuf.nioBuffer();
|
||||
while (written < length) {
|
||||
written += fileChannel.write(byteBuffer);
|
||||
}
|
||||
} else {
|
||||
ByteBuffer[] byteBuffers = byteBuf.nioBuffers();
|
||||
while (written < length) {
|
||||
written += fileChannel.write(byteBuffers);
|
||||
RandomAccessFile accessFile = new RandomAccessFile(dest, "rw");
|
||||
try {
|
||||
FileChannel fileChannel = accessFile.getChannel();
|
||||
try {
|
||||
if (byteBuf.nioBufferCount() == 1) {
|
||||
ByteBuffer byteBuffer = byteBuf.nioBuffer();
|
||||
while (written < length) {
|
||||
written += fileChannel.write(byteBuffer);
|
||||
}
|
||||
} else {
|
||||
ByteBuffer[] byteBuffers = byteBuf.nioBuffers();
|
||||
while (written < length) {
|
||||
written += fileChannel.write(byteBuffers);
|
||||
}
|
||||
}
|
||||
fileChannel.force(false);
|
||||
} finally {
|
||||
fileChannel.close();
|
||||
}
|
||||
} finally {
|
||||
accessFile.close();
|
||||
}
|
||||
|
||||
fileChannel.force(false);
|
||||
fileChannel.close();
|
||||
accessFile.close();
|
||||
return written == length;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.SecureRandom;
|
||||
@ -64,6 +65,43 @@ public class AbstractMemoryHttpDataTest {
|
||||
test.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRenameTo() throws Exception {
|
||||
TestHttpData test = new TestHttpData("test", UTF_8, 0);
|
||||
try {
|
||||
File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
|
||||
tmpFile.deleteOnExit();
|
||||
final int totalByteCount = 4096;
|
||||
byte[] bytes = new byte[totalByteCount];
|
||||
PlatformDependent.threadLocalRandom().nextBytes(bytes);
|
||||
ByteBuf content = Unpooled.wrappedBuffer(bytes);
|
||||
test.setContent(content);
|
||||
boolean succ = test.renameTo(tmpFile);
|
||||
assertTrue(succ);
|
||||
FileInputStream fis = new FileInputStream(tmpFile);
|
||||
try {
|
||||
byte[] buf = new byte[totalByteCount];
|
||||
int count = 0;
|
||||
int offset = 0;
|
||||
int size = totalByteCount;
|
||||
while ((count = fis.read(buf, offset, size)) > 0) {
|
||||
offset += count;
|
||||
size -= count;
|
||||
if (offset >= totalByteCount || size <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertArrayEquals(bytes, buf);
|
||||
assertEquals(0, fis.available());
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
} finally {
|
||||
//release the ByteBuf in AbstractMemoryHttpData
|
||||
test.delete();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Provide content into HTTP data with input stream.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user