mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-06-26 15:13:21 +00:00
![SquidDev](/assets/img/avatar_default.png)
When closing a BufferedWriter, we close the underlying writer. As we're using channels, this is an instance of sun.nio.cs.StreamEncoder. This will attempt to flush the pending character. However, if throwing an exception within .write errors, the flush will fail and so the underlying stream is not closed. This was causing us to leak file descriptors. We fix this by introducing ChannelWrappers - this holds the wrapper object (say, a BufferedWriter) and underlying channel. When closed, we dispose of the wrapper, and then the channel. You could think of this as doing a nested try-with-resources, rather than a single one. Note, this is not related to JDK-6378948 - this occurs in the underlying stream encoder instead.
51 lines
1.3 KiB
Java
51 lines
1.3 KiB
Java
/*
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
*/
|
|
|
|
package dan200.computercraft.core.filesystem;
|
|
|
|
import java.io.Closeable;
|
|
import java.io.IOException;
|
|
import java.nio.channels.Channel;
|
|
|
|
/**
|
|
* Wraps some closeable object such as a buffered writer, and the underlying stream.
|
|
*
|
|
* When flushing a buffer before closing, some implementations will not close the buffer if an exception is thrown
|
|
* this causes us to release the channel, but not actually close it. This wrapper will attempt to close the wrapper (and
|
|
* so hopefully flush the channel), and then close the underlying channel.
|
|
*
|
|
* @param <T> The type of the closeable object to write.
|
|
*/
|
|
class ChannelWrapper<T extends Closeable> implements Closeable
|
|
{
|
|
private final T wrapper;
|
|
private final Channel channel;
|
|
|
|
ChannelWrapper( T wrapper, Channel channel )
|
|
{
|
|
this.wrapper = wrapper;
|
|
this.channel = channel;
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException
|
|
{
|
|
try
|
|
{
|
|
wrapper.close();
|
|
}
|
|
finally
|
|
{
|
|
channel.close();
|
|
}
|
|
}
|
|
|
|
public T get()
|
|
{
|
|
return wrapper;
|
|
}
|
|
}
|