You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@xmlgraphics.apache.org by "Jason Harrop (Jira)" <ji...@apache.org> on 2026/10/11 03:20:00 UTC
[jira] [Created] (XGC-150) ImageLoaderRawPNG never closes its ImageInputStream, so the image file stays open until garbage collection
Jason Harrop created XGC-150:
--------------------------------
Summary: ImageLoaderRawPNG never closes its ImageInputStream, so the image file stays open until garbage collection
Key: XGC-150
URL: https://issues.apache.org/jira/browse/XGC-150
Project: XMLGraphicsCommons
Issue Type: Bug
Components: image codecs
Affects Versions: 2.11
Reporter: Jason Harrop
Attachments: XGC-150.patch
{{ImageLoaderRawPNG.loadImage()}} takes the {{ImageInputStream}} out of the session's {{Source}}, detaches it with {{XmlSourceUtil.removeStreams(src)}} ("Remove streams as we do things with them at some later time"), wraps it for {{PNGFile}}, and never closes it. But {{PNGFile}}'s constructor reads every chunk it keeps (IHDR, PLTE, IDAT, tRNS, iCCP, sRGB) into memory, and {{getImageRawPNG()}} serves the image data from those byte arrays, so nothing reads the stream once {{PNGFile}} has been constructed.
So after FOP renders a PNG (to PDF, say), the PNG's file stays open until the stream is garbage collected, and so does ImageIO's cache file ({{imageio*.tmp}} in {{java.io.tmpdir}}) where the source came from an {{InputStream}}. On Windows an open file can't be deleted, so an application can't remove the image files it has just rendered. Seen from docx4j (https://github.com/plutext/docx4j/issues/609), which writes pictures to temporary files for FOP and deletes them after the conversion: on Linux, {{/proc/self/fd}} still shows the PNG (deleted) and its {{imageio*.tmp}} open once FOP has finished, while a JPEG in the same document has been closed.
Fix: close the stream in a {{finally}} once {{PNGFile}} has read it:
{code:java}
XmlSourceUtil.removeStreams(src);
try {
SeekableStream seekStream = new ImageInputStreamSeekableStreamAdapter(in);
// PNGFile reads the chunks it needs into memory, so the stream is done with after this
PNGFile im = new PNGFile(seekStream, info.getOriginalURI());
return im.getImageRawPNG(info);
} finally {
IOUtils.closeQuietly(in);
}
{code}
with a test, {{ImageLoaderRawPNGTestCase.testLoadImageClosesStream}}, which fails without the fix. The full test suite passes and checkstyle is clean. Patch attached; a PR follows.
Related: XGC-107 ({{ImageLoaderInternalTIFF}} doesn't close its source either).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: general-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: general-help@xmlgraphics.apache.org