From fa423ed722720c6dae22bc2197ffc4eb46f44f35 Mon Sep 17 00:00:00 2001 From: Frank Niessink Date: Fri, 14 Jun 2024 11:46:31 +0200 Subject: [PATCH] Prevent zombie process in renderer. Prevent zombie browser processes by starting Chromium only once and opening and closing a new page for each render. Closes #8979. --- components/renderer/src/index.js | 30 +++++++++++++++++++----------- docs/src/changelog.md | 3 ++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/components/renderer/src/index.js b/components/renderer/src/index.js index d905764a5e..3982b01f53 100644 --- a/components/renderer/src/index.js +++ b/components/renderer/src/index.js @@ -6,21 +6,18 @@ const app = express(); const RENDERER_PORT = process.env.RENDERER_PORT || 9000; const PROXY = `${process.env.PROXY_HOST || 'www'}:${process.env.PROXY_PORT || 80}`; const PROTOCOL = process.env.PROXY_PROTOCOL || 'http'; +let browser app.get("/api/health", async (_req, res) => { - res.status(200).send("OK") + const healthy = browser.connected ?? false + res.status(healthy ? 200 : 503).send(healthy ? "OK" : "Chromium not connected") }) app.get("/api/render", async (req, res) => { + let webPage try { const url = sanitizeUrl(`${PROTOCOL}://${PROXY}/${req.query.path}`); - const browser = await puppeteer.launch({ - defaultViewport: { width: 1500, height: 1000 }, - args: ['--disable-dev-shm-usage', '--no-sandbox'], - // Opt in to new Chrome headless implementation, see https://developer.chrome.com/articles/new-headless/: - headless: "new", - }); - const webPage = await browser.newPage(); + webPage = await browser.newPage(); await webPage.goto(url, { waitUntil: "networkidle2", timeout: 60000 @@ -42,15 +39,26 @@ app.get("/api/render", async (req, res) => { } }); console.log(`URL ${url}: PDF created`); - await browser.close(); res.contentType("application/pdf"); res.send(pdf); } catch (error) { console.error(error) res.sendStatus(500) + } finally { + await webPage.close() } }) -app.listen(RENDERER_PORT, () => { - console.log(`Renderer started on port ${RENDERER_PORT}. Using proxy ${PROXY}`); +app.listen(RENDERER_PORT, async () => { + try { + browser = await puppeteer.launch({ + defaultViewport: { width: 1500, height: 1000 }, + args: ['--disable-dev-shm-usage', '--no-sandbox'], + // Opt in to new Chrome headless implementation, see https://developer.chrome.com/articles/new-headless/: + headless: "new", + }) + console.log(`Renderer started on port ${RENDERER_PORT}. Using proxy ${PROXY}`); + } catch (error) { + console.log(error) + } }); diff --git a/docs/src/changelog.md b/docs/src/changelog.md index 1a17a1bb57..ac723dbf6d 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -17,7 +17,8 @@ If your currently installed *Quality-time* version is not v5.13.0, please first ### Fixed - In the dropdown of the "Add metric" button, keep the two checkboxes next to each other regardless of the width of the menu. Fixes [#8745](https://github.com/ICTU/quality-time/issues/8745). -- The icon of the trend graph tab would not be shown. Closes [#8822](https://github.com/ICTU/quality-time/issues/8822). +- The icon of the trend graph tab would not be shown. Fixes [#8822](https://github.com/ICTU/quality-time/issues/8822). +- Prevent zombie browser processes in the renderer component when creating PDF fails by closing the browser regardless of whether generating the PDF succeeds or not. Fixes [#8979](https://github.com/ICTU/quality-time/issues/8979). ### Added