Recently I've upgraded to Jetty 9.0.5 and found following issue:
Jetty9 DefaultServlet leaves open file descriptors when serving
files with length greater than response's buffer size (32k by default).
Steps to reproduce:
1. launch app using project dir as a working directory;
3. lsof -p ${app_pid} | grep big-file
4. repeat steps [2-3] 5 times
5. the output of lsof will be like:
yohan@yohanbook:~/workspace/project/jetty9-unclosed-files/src$ lsof -p 24647 | grep big-file
java 24647 yohan 56r REG 8,5 422279 995099 /home/yohan/workspace/project/jetty9-unclosed-files/src/big-file.txt
java 24647 yohan 61r REG 8,5 422279 995099 /home/yohan/workspace/project/jetty9-unclosed-files/src/big-file.txt
java 24647 yohan 63r REG 8,5 422279 995099 /home/yohan/workspace/project/jetty9-unclosed-files/src/big-file.txt
java 24647 yohan 65r REG 8,5 422279 995099 /home/yohan/workspace/project/jetty9-unclosed-files/src/big-file.txt
java 24647 yohan 67r REG 8,5 422279 995099 /home/yohan/workspace/project/jetty9-unclosed-files/src/big-file.txt
6. those files are never closed
Source of the problem:
org.eclipse.jetty.server.HttpOutput.sendContent:401:
public void sendContent(HttpContent httpContent, Callback callback) throws IOException
{
if (isClosed())
throw new IOException("Closed");
if (BufferUtil.hasContent(_aggregate))
throw new IOException("written");
if (_channel.isCommitted())
throw new IOException("committed");
ByteBuffer buffer= _channel.useDirectBuffers()?httpContent.getDirectBuffer():null;
if (buffer == null) // we got null if file is > 32kb
buffer = httpContent.getIndirectBuffer();
if (buffer!=null)
{
sendContent(buffer,callback);
return;
}
ReadableByteChannel rbc=httpContent.getReadableByteChannel();
if (rbc!=null) // <---- here we open rbc, that is never closed
{
sendContent(rbc,callback);
return;
}
InputStream in = httpContent.getInputStream(); // btw: if we got here, inputStreams will not be closed too
if ( in!=null )
{
sendContent(in,callback);
return;
}
callback.failed(new IllegalArgumentException("unknown content for "+httpContent));
}
Attached testcase with required dependencies.
-
Kind Regards,
Dima Pekar