SVG text generation with Pango on Windows is not thread safe
See original GitHub issueI’m using .NET NodeServices under aspnetcore 2.1 and loading an image from the filesystem, resizing it and applying a simple SVG overlay containing text.
I was finding that some images ended up with squares instead of the font (Arial):
In addition I’m seeing this in the Node.js output. The only font I use is Arial.
fail: Microsoft.AspNetCore.NodeServices[0] (sharp:17224): Pango-WARNING **: couldn’t load font “Arial Not-Rotated 18”, falling back to “Sans Not-Rotated 18”, expect ugly output. fail: Microsoft.AspNetCore.NodeServices[0] (sharp:17224): Pango-WARNING **: couldn’t load font “Sans Not-Rotated 18”, falling back to “Sans Not-Rotated 18”, expect ugly output. fail: Microsoft.AspNetCore.NodeServices[0] (sharp:17224): Pango-WARNING **: All font fallbacks failed!!! fail: Microsoft.AspNetCore.NodeServices[0] (sharp:17224): Pango-WARNING **: All font fallbacks failed!!! fail: Microsoft.AspNetCore.NodeServices[0] (sharp:17224): Pango-WARNING **: All font fallbacks failed!!! fail: Microsoft.AspNetCore.NodeServices[0] _win32_scaled_font_set_world_transform: The operation completed successfully. fail: Microsoft.AspNetCore.NodeServices[0] _win32_scaled_font_set_world_transform: The handle is invalid.
This only occurs when I simultaneously try to process several images at the same time (eg. when I open my website) so it appears to be some kind of threading issue with Sharp / Pango.
To further experiment, the following code overlays the time onto an image, creates a new buffer and does it again - 50 times.
for (var i = 0; i < 50; i++)
{
const watermarkText = new Date().getTime() % 10000;
const watermark = new Buffer(`<svg width="200" height="500">
<text x="90" y="${i*20}" width="400" height="50" font-size="18" fill="#000000" font-family="Arial" text-anchor="middle">${watermarkText}</text>
</svg>`);
// apply the overlay
compressedImage = compressedImage.overlayWith(watermark, { overlayCutout: true });
// create to buffer so we can do it again
var newImage = await compressedImage.toBuffer({ resolveWithObject: true });
compressedImage = sharp(newImage.data);
}
If I run this only once in my browser I always get a nice clean list like this :
You can see from the timestamps it takes about 2 seconds to process all the overlayWith
and toBuffer
calls.
If I run this only TWICE from two different browser windows I immediately get this every time :
You can see the overlapping timestamps, and that’s when the problem begins.
I’m new to Node.js so maybe there’s a simple ‘thread safe’ option I need to enable, but right now I’m somewhat stuck. This is similar to #1162 but I wanted to start a new issue with a clearer explanation.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:17 (9 by maintainers)
Top GitHub Comments
v0.26.0 now available with prebuilt Windows binaries containing the upstream fix.
It seems that the above PR has been released in Pango v1.45.1. I have updated Pango to v1.45.3 within the libvips Windows binaries used by sharp.
MR https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/38 is not necessary to resolve this issue, since the MXE-binaries uses the FontConfig backend on Windows (to avoid having to link against
gdi32.dll
andmsimg32.dll
).I’ll do some tests with the
v8.10.0-beta2
(pre-release) binaries to check if this issue has been resolved.