fix: prevent desktop log floods and bound log retention

This commit is contained in:
2026-11-03 14:57:57 +03:00
parent c812d49250
commit d23daa5578
3 changed files with 324 additions and 21 deletions
+12 -21
View File
@@ -37,6 +37,7 @@ const fs = require("node:fs");
const http = require("node:http");
const net = require("node:net");
const path = require("node:path");
const { createDesktopLogger } = require("./desktop-logger.cjs");
// Mirrors SIDEBAR_AUTOCLOSE in components/sidebar.tsx — keep in sync (the
// renderer owns the number; this is the IPC widen target).
@@ -143,13 +144,20 @@ let subscriptionChild = null;
let desktopAPISecret = null;
let reopenWindow = null;
const trustedAppWindows = new Set();
const desktopLogger = createDesktopLogger({
directory: () => path.join(app.getPath("userData"), "logs"),
stdout: process.stdout,
stderr: process.stderr,
filesystem: fs,
});
// A GUI shell must never die to a stray exception (EPIPE dialogs, a race
// in an event handler): the window + child server are the product, and
// anything main-side is recoverable by logging it. Log-and-continue.
process.on("uncaughtException", (err) => {
try {
log(`uncaught: ${err?.stack ?? err}`);
// File only: writing to stdout here used to turn EPIPE into a tight loop.
desktopLogger.log(`uncaught: ${err?.stack ?? err}`, { fileOnly: true });
} catch {
/* nothing left to write to */
}
@@ -177,25 +185,7 @@ function freePort() {
* still win over the file inside the child (its documented rule). */
function log(line) {
const stamp = new Date().toISOString();
// The stdout write is guarded (EPIPE hardening, 2026-10-10): a packaged
// app launched with a consumer-owned pipe (a launcher that exits, a
// piped run) must not die on its next log line when the pipe breaks.
// The file below stays the durable channel.
try {
console.log(`[lh ${stamp}] ${line}`);
} catch {
/* stdout gone — userData/logs/main.log still carries it */
}
// Belt and braces: also append to userData/logs so a misbehaving child
// can be diagnosed after the window is gone. Best effort only.
try {
const dir = path.join(app.getPath("userData"), "logs");
fs.mkdirSync(dir, { recursive: true });
fs.appendFileSync(path.join(dir, "main.log"), `[${stamp}] ${line}\n`);
} catch {
/* best effort */
}
desktopLogger.log(line);
}
function startServer(port) {
@@ -656,6 +646,7 @@ async function main() {
process.on("SIGHUP", killServer);
await app.whenReady();
desktopLogger.initialize();
// Dev mode: point at a running `next dev` server (LH_DEV_URL) — no
// spawn, no packaging, full HMR. The rest of this shell still applies
@@ -771,4 +762,4 @@ async function main() {
checkForUpdates();
setInterval(() => checkForUpdates(), UPDATE_CHECK_INTERVAL_MS);
}
}
}