sharp: Windows, SVG, possible font rendering deadlock under load

Possible bug

Is this a possible bug in a feature of sharp, unrelated to installation?

  • Running npm install sharp completes without error.
  • Running node -e "require('sharp')" completes without error.

If you cannot confirm both of these, please open an installation issue instead.

Are you using the latest version of sharp?

  • I am using the latest version of sharp as reported by npm view sharp dist-tags.latest.

If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.

If you are using another package which depends on a version of sharp that is not the latest, please open an issue against that package instead.

What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?

  System:
    OS: Windows 10 10.0.22621
    CPU: (24) x64 AMD Ryzen 9 3900X 12-Core Processor
    Memory: 31.84 GB / 63.93 GB
  Binaries:
    Node: 19.0.0 - C:\Program Files\nodejs\node.EXE
    npm: 8.19.2 - C:\Program Files\nodejs\npm.CMD
  npmPackages:
    sharp: ^0.31.3 => 0.31.3

What are the steps to reproduce?

Sometimes our express server stops responding to requests. I traced it down to our usage of sharp. Sometimes, sharp returns a Promise that neither resolves nor rejects. I’ve isolated the problem into the code below that exhibits the bug. It appears to have something to do with SVG. I force the bug to happen quicker by running many operations in parallel.

What is the expected behaviour?

The program should print Generation 0..99 and then exit.

Instead, the program hangs, usually at the first or after just a few generations. The CPU usage of the process drops to 0.

Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem

import sharp = require("sharp")

const svg = `<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"
    height="846"
    width="540">
    <text
        text-anchor="middle"
        x="50%" y="209"
        font-size="28"
    >
    ${"ABCDEFG ".repeat(20)}
    ${"ABCDEFG ".repeat(20)}
    </text>
    <text
        text-anchor="middle"
        x="50%" y="237"
        font-size="28"
    >
    </text>
</svg>`


main()
    .then(() => console.log("OK"))
    .catch(err => console.log(`Error: ${err}`))

async function main() {
    for (let i = 0; i < 100; i++) {
        console.log(`Generation ${i}`)
        await Promise.all(Array(100).fill(1).map(_ => createImg()))
    }
}

async function createImg() {
    return await sharp({
        create: {
            width: 540,
            height: 846,
            background: { r: 255, g: 255, b: 255 },
            channels: 3,
        }
    })
    .composite([{ input: Buffer.from(svg) }])
    .toBuffer()
}

Please provide sample image(s) that help explain this problem

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (10 by maintainers)

Most upvoted comments

I can confirm that this is indeed a deadlock/race condition issue. It is not caused by Pango (or Fontconfig), but Cairo seems to be the culprit now.

Meme

Cairo, Pango, FreeType (image source: https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/288#note_708038)

Backporting commit https://gitlab.freedesktop.org/cairo/cairo/-/commit/76e0df566595a77e271de523b3d06f86f3e85813 and https://gitlab.freedesktop.org/cairo/cairo/-/commit/a8c1858cf2bb6efb35c0678d135fd522ece9e2a4 from the master branch of Cairo seems to fix this. I also backported commit https://gitlab.freedesktop.org/cairo/cairo/-/commit/531ec8d02db7d3482c3fb65d33dbb50c71b86999 and https://gitlab.freedesktop.org/cairo/cairo/-/commit/166d718099fc8898895d4ad2839d5fb9865a87a5 just to be sure.

@lovell Draft commit https://github.com/libvips/build-win64-mxe/commit/da49a60df2b4dc6b3be24a8f351df97623c43e3b incorporates this in the Windows builds. Let me know if I should make an 8.14.1-build2 release. 😃

I can confirm the problem is solved (at least for me).

v0.32.0 is now available with prebuilt binaries including the latest cairo (and pango). I’ll close as these should fix the original problem, but please feel free to re-open with more details if the issue remains.