diff --git a/electron/gameWindow.js b/electron/gameWindow.js index 0eb3b49d3..7659b0178 100644 --- a/electron/gameWindow.js +++ b/electron/gameWindow.js @@ -43,7 +43,7 @@ async function createWindow(killall) { if (tracker.state.isMaximized) window.maximize(); window.removeMenu(); - noScripts = killall ? { query: { noScripts: killall } } : {}; + const noScripts = killall ? { query: { noScripts: killall } } : {}; window.loadFile("index.html", noScripts); window.once("ready-to-show", () => { utils.setZoomFactor(window, utils.getZoomFactor()); diff --git a/electron/utils.js b/electron/utils.js index a39899169..d317c475f 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -1,18 +1,55 @@ +/** @import { BrowserWindow } from "electron" */ /* eslint-disable @typescript-eslint/no-var-requires */ -const { dialog } = require("electron"); +const { app, dialog } = require("electron"); const log = require("electron-log"); const Store = require("electron-store"); const store = new Store(); const arg = require("arg"); +/** @param {BrowserWindow} window */ +function getRendererProcessUniqueId(window) { + const rendererProcesses = app + .getAppMetrics() + .filter((processMetric) => processMetric.pid === window.webContents.getOSProcessId()); + if (rendererProcesses.length === 0) { + return null; + } + // This should never happen. + if (rendererProcesses.length > 1) { + log.error("Found more than 1 renderer process"); + log.info(rendererProcesses); + } + const rendererProcess = rendererProcesses[0]; + // Pid may be reused, so we need to use both pid and creationTime to uniquely identify the process. + return `${rendererProcess.pid}-${rendererProcess.creationTime}`; +} + +/** + * @param {BrowserWindow} window + * @param {boolean} killScripts + */ function reloadAndKill(window, killScripts) { log.info("Reloading & Killing all scripts..."); const zoomFactor = getZoomFactor(); + const currentRendererProcessUniqueId = getRendererProcessUniqueId(window); + log.debug(`Current renderer process unique id: ${currentRendererProcessUniqueId}`); window.webContents.forcefullyCrashRenderer(); window.loadFile("index.html", killScripts ? { query: { noScripts: true } } : {}); window.once("ready-to-show", () => { setZoomFactor(window, zoomFactor); }); + // Keep checking whether a new renderer process has been spawned. If not, call loadFile. We need to do this to + // mitigate the issue of forcefullyCrashRenderer. + // Check https://github.com/electron/electron/issues/48661 for more information. + const intervalId = setInterval(() => { + const rendererProcessUniqueId = getRendererProcessUniqueId(window); + log.debug(`Renderer process unique id: ${rendererProcessUniqueId}`); + if (rendererProcessUniqueId !== null && rendererProcessUniqueId !== currentRendererProcessUniqueId) { + clearInterval(intervalId); + return; + } + window.loadFile("index.html", killScripts ? { query: { noScripts: true } } : {}); + }, 0); } function promptForReload(window) {