I am looking at implementation of IOUtils.copy() from Apache Commons at http://www.docjar.com/html/api/org/apache/commons/io/IOUtils.java.html and it eventually boils down to:
public static long copyLarge(InputStream input, OutputStream output)
throws IOException {
// DEFAULT_BUFFER_SIZE is 4096
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
I am running this in an Executor, the task has a timeout etc. but if I understand correctly even if it times out and the Future is cancelled, the thread keeps on running because there is no check for thread status anywhere in this loop. This leads to a dangerous leak and starvation.
Seems like I need to rewrite the loop, but what is the sane and correct way to handle this? throw new IOException(new InterruptedException())? Declare the method as throwing InterruptedException and throw it (hate to do it for all my IO helper methods)?
EDIT: I just checked ByteStreams from Guava and they seem to be doing the same thing. Now I’m wondering why the two major libraries don’t support interruptions in such loop. Am I missing something?
If you close
inputand/oroutput, thecopyLargemethod will throw an exception, exiting the loop.