mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-06 05:32:06 +00:00
Fix Electron shutdown by terminating NodeCG process tree (#13)
* Fix Electron shutdown by terminating NodeCG process tree * fix: adjust window dimensions for main and loading screens
This commit is contained in:
+83
-18
@@ -25,15 +25,17 @@ let mainWindow: BrowserWindow | null = null;
|
||||
let loadingWindow: BrowserWindow | null = null;
|
||||
let nodecgProcess: ChildProcess | null = null;
|
||||
let lastNodeCGOutput = "";
|
||||
let stopNodeCGPromise: Promise<void> | null = null;
|
||||
let isQuitting = false;
|
||||
|
||||
function createMainWindow(): BrowserWindow {
|
||||
const win = new BrowserWindow({
|
||||
show: false,
|
||||
title: APP_TITLE,
|
||||
width: 1440,
|
||||
height: 900,
|
||||
minWidth: 960,
|
||||
minHeight: 640,
|
||||
width: 1280,
|
||||
height: 800,
|
||||
minWidth: 800,
|
||||
minHeight: 500,
|
||||
backgroundColor: "#0f0f0f",
|
||||
webPreferences: {
|
||||
contextIsolation: true,
|
||||
@@ -73,8 +75,8 @@ function createLoadingWindow(): BrowserWindow {
|
||||
show: false,
|
||||
frame: false,
|
||||
title: APP_TITLE,
|
||||
width: 420,
|
||||
height: 280,
|
||||
width: 300,
|
||||
height: 300,
|
||||
resizable: false,
|
||||
movable: true,
|
||||
minimizable: false,
|
||||
@@ -180,6 +182,7 @@ function startNodeCG(): ChildProcess {
|
||||
...(USE_SYSTEM_NODE ? {} : { ELECTRON_RUN_AS_NODE: "1" }),
|
||||
},
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
detached: process.platform !== "win32",
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
|
||||
@@ -277,23 +280,76 @@ async function launch(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
function stopNodeCG(): void {
|
||||
function killNodeCGProcessTree(pid: number, signal: NodeJS.Signals): boolean {
|
||||
if (process.platform === "win32") {
|
||||
const force = signal === "SIGKILL" ? "/F" : "";
|
||||
const killer = spawn("taskkill", ["/pid", String(pid), "/T", ...(force ? [force] : [])], {
|
||||
stdio: "ignore",
|
||||
shell: true,
|
||||
});
|
||||
|
||||
killer.on("error", (error) => {
|
||||
log(`taskkill error for pid=${pid}`, error);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
process.kill(-pid, signal);
|
||||
return true;
|
||||
} catch {
|
||||
try {
|
||||
process.kill(pid, signal);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stopNodeCG(): Promise<void> {
|
||||
if (stopNodeCGPromise) {
|
||||
return stopNodeCGPromise;
|
||||
}
|
||||
|
||||
if (!nodecgProcess || nodecgProcess.killed) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const processToStop = nodecgProcess;
|
||||
const pid = processToStop.pid;
|
||||
|
||||
log(`Stopping NodeCG pid=${pid}`);
|
||||
processToStop.kill("SIGTERM");
|
||||
if (typeof pid !== "number") {
|
||||
log("NodeCG pid unavailable, skipping graceful stop");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (processToStop.exitCode === null && processToStop.signalCode === null) {
|
||||
log(`NodeCG did not exit after SIGTERM, forcing SIGKILL pid=${pid}`);
|
||||
processToStop.kill("SIGKILL");
|
||||
}
|
||||
}, Math.max(0, NODECG_KILL_TIMEOUT_MS));
|
||||
log(`Stopping NodeCG pid=${pid}`);
|
||||
killNodeCGProcessTree(pid, "SIGTERM");
|
||||
|
||||
stopNodeCGPromise = new Promise((resolve) => {
|
||||
const complete = () => {
|
||||
if (nodecgProcess === processToStop) {
|
||||
nodecgProcess = null;
|
||||
}
|
||||
stopNodeCGPromise = null;
|
||||
resolve();
|
||||
};
|
||||
|
||||
processToStop.once("exit", () => {
|
||||
complete();
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
if (processToStop.exitCode === null && processToStop.signalCode === null) {
|
||||
log(`NodeCG did not exit after SIGTERM, forcing SIGKILL pid=${pid}`);
|
||||
killNodeCGProcessTree(pid, "SIGKILL");
|
||||
}
|
||||
}, Math.max(0, NODECG_KILL_TIMEOUT_MS));
|
||||
});
|
||||
|
||||
return stopNodeCGPromise;
|
||||
}
|
||||
|
||||
function log(...args: unknown[]): void {
|
||||
@@ -331,8 +387,17 @@ app.on("window-all-closed", () => {
|
||||
}
|
||||
});
|
||||
|
||||
app.on("before-quit", () => {
|
||||
stopNodeCG();
|
||||
app.on("before-quit", (event) => {
|
||||
if (isQuitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
isQuitting = true;
|
||||
|
||||
stopNodeCG().finally(() => {
|
||||
app.quit();
|
||||
});
|
||||
});
|
||||
|
||||
app.on("will-quit", () => {
|
||||
|
||||
Reference in New Issue
Block a user