Hello Chris,
> -----Ursprüngliche Nachricht-----
> Von: Christopher Schultz <[email protected]>
> Gesendet: Donnerstag, 16. Juni 2022 05:38
> An: [email protected]
> Betreff: Re: AW: Filehandle left open when using sendfile
>
> Thomas,
>
> On 6/15/22 02:26, Thomas Hoffmann (Speed4Trade GmbH) wrote:
> > Hello Christopher,
> >
> >> -----Ursprüngliche Nachricht-----
> >> Von: Christopher Schultz <[email protected]>
> >> Gesendet: Dienstag, 14. Juni 2022 20:26
> >> An: [email protected]
> >> Betreff: Re: Filehandle left open when using sendfile
> >>
> >> Thomas,
> >>
> >> On 6/14/22 13:52, Thomas Hoffmann (Speed4Trade GmbH) wrote:
> >>> Hello,
> >>> we are using Tomcat 10.0.16 under windows.
> >>> For sending files to the browser, we are using sendfile by setting
> >>> the
> >> attribute "org.apache.tomcat.sendfile.filename".
> >>> Streaming an image to the browser works well in this way.
> >>> But we observed that if the user tries to delete the file
> >>> afterwards, there is
> >> still a file-handle on this file.
> >>
> >> Which user? Some admin on the server, or the user using the browser?
> >> (Dumb question, I know, but tb and ff had a bug for a while where
> >> downloads would leave dangling file handles, disallowing deleting
> >> those files after they were downloaded.)
> >>
> >>> I took a look at NioEndpoint.java -->
> >>>
> >>
> https://github.com/apache/tomcat/blob/main/java/org/apache/tomcat/uti
> >> l
> >>> /net/NioEndpoint.java
> >>>
> >>> At line 869 there is a stream opened:
> >>> FileInputStream fis = new FileInputStream(f);
> >>>
> >>> However, there is no close in this method. Maybe this might cause
> >>> the
> >> open file-handle?
> >>
> >> Did you read the line above that?
> >>
> >> @SuppressWarnings("resource") // Closed when channel is closed
> >> FileInputStream fis = new FileInputStream(f);
> >>
> >> The channel itself is cleaned-up properly and, with it, the file handle.
> >>
> >>
> https://github.com/apache/tomcat/blob/69b9a3eeee41062dc1930782941bb
> >> aa1880e9281/java/org/apache/tomcat/util/net/NioEndpoint.java#L1226
> >>
> >> (At least, I *think* this is where the cleanup happens. I'm not very
> >> well- versed in the connection-handling code in Tomcat.)
> >>
> >>> We are using protocol="org.apache.coyote.http11.Http11NioProtocol"..
> >>> I
> >> think there are different implementations for sendfile-feature.
> >>> The open file-handle can be observer via ProcessExplorer from
> Microsoft.
> >>
> >> How long did you wait for the file handle to close?
> >>
> >> Are you able to attach a debugger and see that the object hasn't been
> >> cleaned-up?
> >>
> >> -chris
> >>
> >
> > Thanks for taking a look at it.
> > Sorry, if the setup was not described in detail. Maybe you can imagine an
> image library, hosted server-side.
> > The user can upload pics and after upload the user can also decide to
> delete the image.
>
> Light bulb: are you using ImageIO?
ImageIO is not used. The pictures are saved as they are without modification.
>
> There have been some well-known leaks in there over the years. It's also
> *very* easy to leak file handles if you aren't managing your resources
> appropriately.
>
> Are you *sure* you have clean use of resources within your own code?
>
> If you are using *any* of Java's javax.imageio code, is it possible to skip
> that
> and re-try your test? Can you e.g. upload a plain text file (or even an image)
> and only stream the bytes from client -> disk without doing anything else?
>
> > Requests:
> > 1) POST-Request with image upload. Server saves the image in the file
> system and returns the URL.
> > 2) GET-Request, the browser requests the URL of the uploaded picture.
> > Server is sending the file via sendfile
> > 3) POST-Request with command to delete the picture (maybe user doesn’t
> > like the pic). Tomcat tries to delete the file on the server side but
> > fails because of the left handle in step 2
>
> Are you sure it's from step #2 and not step #1?
At first I was hunting the problem at step 1)
After a while I figured out, that it is indeed happening in 2)
The following sample reproduces the orphaned file handle under Windows:
<%@page import="java.io.*"%>
<%@page import="java.net.*"%>
<%@page import="org.apache.coyote.Constants"%>
<%
String fileName = "c:\\temp\\test.png";
File file = new File(fileName);
long l = file.length();
request.setAttribute(Constants.SENDFILE_FILENAME_ATTR,
file.getAbsolutePath());
request.setAttribute(Constants.SENDFILE_FILE_START_ATTR, 0L);
request.setAttribute(Constants.SENDFILE_FILE_END_ATTR, l);
response.setHeader("Content-Length", Long.toString(l));
response.setContentType(URLConnection.guessContentTypeFromName(fileName));
response.flushBuffer();
%>
>
> > The handle stays for several minutes for sure.
> >
> > It is hard to debug because when stepping through, the file-handle is gone
> after processing the request.
>
> That seems suspicious if you are saying that Tomcat is definitely leaving the
> file handle open.
>
> > I think there are some if-statements whether the transmission is pending
> or finished.
> > The mentioned line in the NIOEndpoint is not reached. So the file handle
> must be left somewhere else. My first assumption was wrong.
>
> Does the problem go away if you disable sendfile and stream the file
> directly?
>
> -chris
>
Problem goes away when I stream it manually via commons-io:
IOUtils.copy(is, response.getOutputStream());
The handle gets opened via this code within Http2AsyncUpgradeHandler.java:
protected SendfileState processSendfile(SendfileData sendfile) {
if (sendfile != null) {
try {
try (FileChannel channel = FileChannel.open(sendfile.path,
StandardOpenOption.READ)) {
sendfile.mappedBuffer = channel.map(MapMode.READ_ONLY,
sendfile.pos, sendfile.end - sendfile.pos);
}
......
In the meantime I stumbled upon this bug-Report:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4715154
So maybe the problem lies even deeper.
Similar description here:
https://cemerick.com/blog/2006/08/30/memory-mapping-files-in-java-causes-problems.html
Some ppl suggest to use java.lang.ref.Cleaner or don’t use Memory-Mapped files
under Windows.
I don’t know if there are other solutions.
Greetings,
Thomas
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]