Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix font filehandle leak #215

Merged
merged 5 commits into from
Apr 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.awt.*;
import java.text.BreakIterator;
Expand Down Expand Up @@ -167,10 +166,6 @@ public FontResolver getFontResolver() {
return fontResolver;
}

public void flushFonts() {
fontResolver.flushCache();
}

/**
* The media for this context
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class PdfBoxFontResolver implements FontResolver {
private Map<String, FontDescription> _fontCache = new HashMap<String, FontDescription>();
private final PDDocument _doc;
private final SharedContext _sharedContext;
private List<TrueTypeCollection> _collectionsToClose = new ArrayList<TrueTypeCollection>();

public PdfBoxFontResolver(SharedContext sharedContext, PDDocument doc) {
_sharedContext = sharedContext;
Expand All @@ -70,10 +71,42 @@ public FSFont resolveFont(SharedContext renderingContext, FontSpecification spec
return resolveFont(renderingContext, spec.families, spec.size, spec.fontWeight, spec.fontStyle, spec.variant);
}

/**
* Free all font resources (i.e. open files), the document should already be
* closed.
*/
public void close() {
for (FontDescription fontDescription : _fontCache.values()) {
/*
* If the font is not yet subset, we must subset it, otherwise we may leak a
* file handle because the PDType0Font may still have the font file open.
*/
if (fontDescription._font != null && fontDescription._font.willBeSubset()) {
try {
fontDescription._font.subset();
} catch (IOException e) {
e.printStackTrace();
}
}
}
_fontCache.clear();

// Close all still open TrueTypeCollections
for (TrueTypeCollection collection : _collectionsToClose) {
try {
collection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
_collectionsToClose.clear();
}

@Deprecated
@Override
public void flushCache() {
_fontFamilies = createInitialFontMap();
close();
_fontCache = new HashMap<String, FontDescription>();
}

Expand Down Expand Up @@ -160,10 +193,26 @@ private void addFont(TrueTypeFont trueTypeFont, String fontFamilyNameOverride,

PDFont font = PDType0Font.load(_doc, trueTypeFont, subset);

addFont(font, fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
addFontLazy(new PDFontSupplier(font), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
}

private static class PDFontSupplier implements FSSupplier<PDFont> {
private final PDFont _font;

PDFontSupplier(PDFont font) {
_font = font;
}

@Override
public PDFont supply() {
return _font;
}
}

private void addFont(PDFont font, String fontFamilyNameOverride, Integer fontWeightOverride, IdentValue fontStyleOverride, boolean subset) {
/**
* Add a font with a lazy loaded PDFont
*/
private void addFontLazy(FSSupplier<PDFont> font, String fontFamilyNameOverride, Integer fontWeightOverride, IdentValue fontStyleOverride, boolean subset) {
FontFamily<FontDescription> fontFamily = getFontFamily(fontFamilyNameOverride);
FontDescription descr = new FontDescription(
_doc,
Expand Down Expand Up @@ -191,6 +240,7 @@ public void process(TrueTypeFont ttf) throws IOException {
addFont(ttf, fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
}
});
_collectionsToClose.add(collection);
}

/**
Expand Down Expand Up @@ -235,7 +285,29 @@ public void addFont(File fontFile, final String fontFamilyNameOverride, final In
/*
* We load the font using the file.
*/
addFont(PDType0Font.load(_doc, fontFile), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
addFontLazy(new FilePDFontSupplier(fontFile, _doc), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
}

/**
* Loads a Type0 font on demand
*/
private static class FilePDFontSupplier implements FSSupplier<PDFont> {
private final File _fontFile;
private final PDDocument _doc;

FilePDFontSupplier(File fontFile, PDDocument doc) {
this._fontFile = fontFile;
this._doc = doc;
}

@Override
public PDFont supply() {
try {
return PDType0Font.load(_doc, _fontFile);
} catch (IOException e) {
return null;
}
}
}


Expand Down Expand Up @@ -517,6 +589,7 @@ public static class FontDescription implements MinimalFontDescription {
private final PDDocument _doc;

private FSSupplier<InputStream> _supplier;
private FSSupplier<PDFont> _fontSupplier;
private PDFont _font;

private float _underlinePosition;
Expand All @@ -531,10 +604,6 @@ private FontDescription(PDFont font, IdentValue style, int weight) {
this(null, font, style, weight);
}

public FontDescription(PDDocument doc, PDFont font) {
this(doc, font, IdentValue.NORMAL, 400);
}

private FontDescription(PDDocument doc, FSSupplier<InputStream> supplier, int weight, IdentValue style) {
this._supplier = supplier;
this._weight = weight;
Expand All @@ -550,8 +619,21 @@ private FontDescription(PDDocument doc, PDFont font, IdentValue style, int weigh
_doc = doc;
setMetricDefaults();
}


private FontDescription(PDDocument doc, FSSupplier<PDFont> fontSupplier, IdentValue style, int weight) {
_fontSupplier = fontSupplier;
_style = style;
_weight = weight;
_supplier = null;
_doc = doc;
}

private boolean realizeFont(boolean subset) {
if (_font == null && _fontSupplier != null) {
_font = _fontSupplier.supply();
setMetricDefaults();
_fontSupplier = null;
}
if (_font == null && _supplier != null) {
InputStream is = _supplier.supply();
_supplier = null; // We only try once.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,10 @@ public void cleanup() {
_outputDevice.close();
_sharedContext.removeFromThread();
ThreadCtx.cleanup();


// Close all still open font files
((PdfBoxFontResolver)getSharedContext().getFontResolver()).close();

if (_svgImpl != null) {
try {
_svgImpl.close();
Expand Down