Hello Chris, > -----Ursprüngliche Nachricht----- > Von: Christopher Schultz <ch...@christopherschultz.net> > Gesendet: Donnerstag, 16. Juni 2022 05:38 > An: users@tomcat.apache.org > 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 <ch...@christopherschultz.net> > >> Gesendet: Dienstag, 14. Juni 2022 20:26 > >> An: users@tomcat.apache.org > >> 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: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org