chore: event-loop stall detectors for hang diagnosis

WER records AppHangTransient with no stack, so measure lag in both
processes and log it on recovery: [main] event loop stalled / [renderer]
main thread stalled. Tells a main-process block from a renderer freeze
the next time the app 'freezes then recovers'.
This commit is contained in:
Bill committed 2026-09-20 22:25:23 +08:00
1 parent 258e5fac0c
commit f128c3e8be
2 files changed
+25

No files matched your search

+12
View File
@@ -167,6 +167,18 @@ process.on('uncaughtException', (err) => {
console.error('[main] uncaughtException:', err)
})
// Diagnostics for "app froze then recovered" reports: WER logs an
// AppHangTransient but keeps no stack. A stall of THIS (UI) thread is what
// Windows flags as a hang, so measure event-loop lag and say so loudly when
// it happens — that distinguishes a main-process block from a renderer one.
let lastTick = Date.now()
setInterval(() => {
const now = Date.now()
const lag = now - lastTick - 1000
if (lag > 2000) console.error(`[main] event loop stalled ~${lag}ms`)
lastTick = now
}, 1000).unref()
app.on('before-quit', () => {
// Let window 'close' events pass through so teardown completes.
markQuitting()
+13
View File
@@ -11,6 +11,19 @@ import { useSettingsStore } from './settings/store'
import { mix } from './theme/chrome'
import './global.css'
// Diagnostics: report renderer main-thread freezes after recovery. console.error
// is surfaced into the dev terminal by the main process's console-message hook,
// so a "卡死又恢复" report tells us which process stalled and for how long.
{
let lastTick = performance.now()
setInterval(() => {
const now = performance.now()
const lag = now - lastTick - 2000
if (lag > 3000) console.error(`[renderer] main thread stalled ~${Math.round(lag)}ms`)
lastTick = now
}, 2000)
}
// Dev convenience: allow opening the renderer in a plain browser (vite page)
// so layout/UX work doesn't require the electron shell. No-op under electron.
if (typeof window !== 'undefined' && !window.api) {