Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[jetty-dev] Fwd: Jetty9 DefaultServlet leaves open file descriptors when serving files with length greater than response's buffer size.

Good day.

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

Attachment: jetty9-unclosed-files.zip
Description: Zip archive


Back to the top